З терміналом: Використання регулярних виразів II: Заміни

В собі попередня стаття На базовому рівні я розповів вам, як працює кожен із найбільш часто використовуваних спеціальних символів регулярних виразів. За допомогою цих регулярних виразів можна виконувати складний пошук у текстових файлах або у виведенні інших команд. У цій статті я збираюся пояснити, як за допомогою команди sed знаходити та замінювати текст набагато потужнішим способом, ніж просто змінювати один текст на інший.

Трохи більше про команду grep

Перш ніж почати говорити про sed, я хотів би ще трохи прокоментувати команду grep, щоб трохи завершити те, що було пояснено в попередній статті. Все, що я скажу, буде актуальним і для цього. Пізніше ми побачимо взаємозв'язок між цим та пошуковими запитами.

Поєднання регулярних виразів

Багато спеціальних символів, про які я говорив у попередній статті, можна поєднувати не лише з іншими символами, але і з цілими регулярними виразами. Це можна зробити за допомогою дужок, щоб сформувати підвираз. Побачимо приклад цього. Почнемо із завантаження тексту, який ми можемо використовувати для тестування. Це перелік фраз. Для цього ми будемо використовувати таку команду:

curl http://artigoo.com/lista-de-frases-comparativas-comicas 2>/dev/null | sed -n 's/.*\(.*\.\)<\/p>/\1/gp' > frases

 Це залишить вас у каталозі, де ви запускаєте файл із назвою «фрази». Ви можете відкрити його, щоб поглянути на нього і трохи посміятися. 🙂

Тепер припустимо, що ми хочемо знайти фрази, які мають рівно 6 слів. Складність полягає у формуванні регулярного виразу, який відповідає кожному слову. Слово - це послідовність букв, або великих, або малих, що було б приблизно так '[a-zA-Z]+', але ви також повинні вказати, що ці літери повинні бути розділені іншими символами, крім літер, тобто це було б щось на зразок '[a-zA-Z]+[^a-zA-Z]+'. Давайте пам’ятатимемо: «^» як перший символ у дужках вказує на те, що ми хочемо збігатися з символами, які не входять в діапазони, а «+» позначає 1 або більше символів.

У нас уже є регулярний вираз, який може відповідати слову. Щоб поєднати його з 6, його доведеться повторити 6 разів. Для цього ми використовували клавіші, але марно ставити '[a-zA-Z]+[^a-zA-Z]+{6}', оскільки 6 буде повторювати останню частину регулярного виразу, і те, що ми хочемо, - це повторити все, так що ви повинні поставити це: '([a-zA-Z]+[^a-zA-Z]+){6}'. З дужками утворюємо підвираз, а з фігурними дужками повторюємо його 6 разів. Тепер вам просто потрібно додати "^" спереду і "$" ззаду, щоб відповідати всьому рядку. Команда така:

grep -E '^([a-zA-Z]+[^a-zA-Z]+){6}$' frases

І результат - саме те, що ми хотіли:

Вона оспівана більше, ніж Макарена. Ви закінчили більше, ніж Луїс Агіле. У вас менше культури, ніж у каменю. Ви знаєте більше мов, ніж Каніта Брава. У нього більше зморшок, ніж у Тутана Хамона. Ви менше, ніж Рембо, знаєте про догляд за дітьми.

Зверніть увагу, що ми встановлюємо параметр -E, оскільки ми хочемо використовувати розширені регулярні вирази, щоб "+" працював. Якби ми використовували основні, нам довелося б уникнути дужок та дужок.

Попередні посилання або зворотні посилання

Якщо у вас встановлена ​​перевірка правопису, у вас, ймовірно, буде список слів у /usr/share/dict/words. Якщо ні, ви можете встановити його в арку за допомогою:

sudo pacman -S words

Або в debian з:

sudo aptitude install dictionaries-common

Якщо ви хочете, ви можете поглянути на файл, щоб побачити, які слова в ньому є. Насправді це посилання на файл слів мови, на якій знаходиться ваш дистрибутив. Ви можете встановити кілька файлів слів одночасно.

Ми збираємось використовувати цей файл. Виявляється, нам дуже цікаво знати всі там семилітерні паліндроми. Для тих, хто не знає: паліндром - це слово capicúa, тобто його можна читати зліва направо, а також справа наліво. Спробуємо наступну команду:

grep '^\(.\)\(.\)\(.\).\3\2\1$' /usr/share/dict/words

Це виглядає трохи дивно, так? Якщо ми спробуємо, результат буде залежати від мови вашого дистрибутива та слів у вашому списку, але в моєму випадку для іспанської мови результат такий:

анілін анілін прокатки

Давайте подивимось, як працює цей регулярний вираз.

Окрім "^" і "$", для яких ми вже знаємо, для чого це перше, перше, що ми бачимо зліва, це три групи крапок, укладених у дужки. Нехай вас не бентежать стовпчики перед кожною дужкою. Вони повинні уникати дужок, оскільки ми використовуємо основні регулярні вирази, але вони не мають іншого значення. Важливо те, що ми просимо ввести будь-які три символи з крапками, але кожна з цих крапок укладена в дужки. Це робиться для збереження символів, що відповідають цим пунктам, щоб на них можна було знову посилатись із регулярного виразу. Це ще одне використання дужок, яке стане в нагоді пізніше при заміні.

Ось де три цифри нижче знаходяться зі скісною рискою перед ними. У цьому випадку важлива планка. Це означає, що вказане нижче число є зворотним посиланням і посилається на одну з попередніх дужок. Наприклад: \ 1 відноситься до першої дужки, \ 2 до другої тощо.

Тобто, з регулярним виразом, який ми ввели, ми шукаємо всі слова, які починаються з будь-яких чотирьох букв, а потім мають букву, яка збігається з третьою, інша така ж, як друга і інша це те саме, що і перший. Результат - семилітерні паліндроми, які є у списку слів. Так само, як ми хотіли.

Якби ми використовували розширені регулярні вирази, нам не довелося б уникати дужок, але з розширеними регулярними виразами зворотні посилання не працюють у всіх програмах, оскільки вони не стандартизовані. Однак з grep вони працюють, тож це може бути іншим способом зробити те саме. Ви можете спробувати, якщо хочете.

Вирази заміни: команда sed

Окрім пошуку, одним із найкращих варіантів використання регулярних виразів є заміна складних текстів. Для цього один із способів зробити це за допомогою команди sed. Потужність команди sed виходить далеко за рамки заміни текстів, але тут я збираюся використати її для цього. Синтаксис, який я збираюся використовувати з цією командою, такий:

sed [-r] 's/REGEX/REPL/g' FICHERO

Або також:

COMANDO | sed [-r] 's/REGEX/REPL/g'

Де REGEX буде регулярним виразом пошуку, а REPL - заміним. Майте на увазі, що ця команда насправді не замінює нічого у файлі, який ми вказуємо, але те, що вона робить, це показує нам результат заміни в терміналі, тому не лякайтесь команд, які я збираюся ввести далі. Жоден з них не збирається змінювати будь-які файли у вашій системі.

Почнемо з простого прикладу. У всіх нас є різні файли конфігурації в каталозі / etc, які зазвичай мають коментарі, що починаються на "#". Припустимо, ми хочемо бачити один із цих файлів без коментарів. Наприклад, я збираюся це зробити за допомогою fstab. Ви можете спробувати з тим, який хочете.

sed 's/#.*//g' /etc/fstab

Я не збираюся розміщувати результат команди тут, оскільки це залежить від того, що у вас є у вашому fstab, але якщо ви порівняєте висновок команди із вмістом файлу, то побачите, що всі коментарі зникли.

У цій команді пошуковий вираз «#.*", Тобто" # ", за яким слід будь-яка кількість символів, тобто коментарі. І вираз заміни, якщо ви подивитесь на дві смуги поспіль, ви побачите, що їх немає, тож те, що він робить, - це замінити коментарі нічим, тобто видалити їх. Простіше неможливо.

Зараз ми будемо робити навпаки. Припустимо, що ми хочемо прокоментувати всі рядки файлу. Спробуємо так:

sed 's/^/# /g' /etc/fstab

Ви побачите, що на виході команди всі рядки починаються з позначки хешу та пробілу. Ми зробили заміну початку рядка на «# «. Це також досить простий приклад, коли текст, який потрібно замінити, завжди однаковий, але зараз ми ще трохи ускладнимо його.

Витонченість заміни полягає в тому, що у виразі заміни ви можете використовувати зворотні посилання, подібні до тих, про які я вже говорив вам раніше. Повернемося до файлу фраз, який ми завантажили на початку статті. Ми збираємося вставити в дужки всі великі літери, які є, але ми зробимо це за командою:

sed 's/\([A-Z]\)/(\1)/g' frases

Тут ми маємо зворотне посилання у виразі заміни, яке посилається на дужки у виразі пошуку. Дужки у виразі, що замінює, є звичайними дужками. У виразі заміни вони не мають особливого значення, вони вводяться як є. Результат полягає в тому, що всі великі літери замінюються на ту саму букву, якою б вона не була, навколо неї - дужки.

Існує ще один символ, який також може бути використаний у виразі заміни, це "&", і він замінюється всім текстом, що відповідає виразу пошуку. Прикладом цього може бути розміщення всіх фраз у файлі в лапках. Цього можна досягти за допомогою цієї команди:

sed 's/.*/"&"/g' frases

Операція цієї команди дуже схожа на попередню, лише зараз ми замінюємо весь рядок з однаковим рядком із лапками навколо нього. Оскільки ми використовуємо "&", не потрібно ставити дужки.

Деякі корисні команди з регулярними виразами

Ось кілька команд, які мені здаються корисними чи цікавими, і які використовують регулярні вирази. За допомогою цих команд корисність регулярних виразів набагато краща, ніж у прикладах, які я наводив до цього часу, але мені здавалося важливим пояснити щось про те, як працюють регулярні вирази, щоб зрозуміти їх.

  • Показати розділи сторінки користувача:

man bash | grep '^[A-Z][A-Z ]*$'

Звичайно, ви можете змінити команду bash як завгодно. І тоді від людини ви можете перейти безпосередньо до розділу, який вас цікавить, використовуючи, звичайно, регулярний вираз. Ви натискаєте «/», щоб розпочати пошук і написати «^ALIASES$»Перейти, наприклад, до розділу ПСИХІМИ. Думаю, це перше використання регулярних виразів, яке я почав використовувати кілька років тому. Переміщення деяких сторінок посібника майже неможливе без такого фокусу.

  • Покажіть імена всіх користувачів машини, включаючи спеціальних:

sed 's/\([^:]*\).*/\1/' /etc/passwd

  • Показувати імена користувачів, але лише ті з оболонкою:

grep -vE '(/false|/nologin)$' /etc/passwd | sed 's/\([^:]*\).*/\1/g'

Це дійсно можна зробити за допомогою одного регулярного виразу, але спосіб зробити це виходить за рамки того, що я сказав вам у цих статтях, тому я зробив це, поєднавши дві команди.

  • Вставте кому перед останніми трьома цифрами всіх чисел у файлі чисел:

sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers

Він працює лише з числами до 6 цифр, але його можна викликати більше одного разу, щоб розмістити роздільники в інших групах із трьох цифр.

  •  Витягніть усі адреси електронної пошти з файлу:

grep -E '\<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}\>' FICHERO

  • Відокремте день, місяць і рік усіх дат, які з’являються у файлі:

sed -r 's/([0-9]{2})[/-]([0-9]{2})[/-]([0-9]{4})/Día: \1, Mes: \2, Año: \3/g' FICHERO

  • Дізнайтеся наш локальний IP:

/sbin/ifconfig | grep 'inet .*broadcast' | sed -r 's/[^0-9]*(([0-9]+\.){3}[0-9]+).*/\1/g'

Це також можна зробити за допомогою однієї команди sed, але мені краще розділити її на grep та sed для простоти.

Кілька корисних адрес

Ось кілька адрес, які можуть бути корисними стосовно регулярних виразів:

  • Бібліотека регулярних виразів: Це бібліотека регулярних виразів, у якій ви можете шукати регулярні вирази, що стосуються теми, яка вас цікавить. Для пошуку веб-адрес, посвідчення особи або будь-чого іншого.
  • RegExr: Інтернет-перевірка регулярних виразів. Це дозволяє вводити текст і застосовувати до нього регулярний вираз або шукати, або замінювати. Він надає інформацію про регулярний вираз, і у вас є кілька варіантів змінити його поведінку.
  • Тестер регулярних виразів: Це аддон для firefox, який дозволяє перевіряти регулярні вирази з браузера.

Висновок

Наразі це все. Регулярні вирази складні, але корисні. Щоб їх вивчити, потрібен час, але якщо ви схожі на мене, грати з ними здаватиметься веселою, і потроху ви їх освоїте. Це цілий світ. Ще можна багато сказати про ліниві квантори, регулярний вираз у стилі PERL, багаторядковий тощо. І тоді кожна програма має свої характеристики та свої варіанти, тому найкраща порада, яку я можу вам дати, - це завжди переглядати документацію програми, яку ви використовуєте, кожного разу, коли вам доводиться писати регулярний вираз у новій програмі.

Гей! ... ГЕЙ! … ПРОКИДАЙСЯ! ... ЩО ВСІ ВСІ СПИТИ? 🙂

Фуентес

Деякі ідеї та приклади регулярних виразів у цій статті я взяв звідси:


Залиште свій коментар

Ваша електронна адреса не буде опублікований. Обов'язкові для заповнення поля позначені *

*

*

  1. Відповідальний за дані: Мігель Анхель Гатон
  2. Призначення даних: Контроль спаму, управління коментарями.
  3. Легітимація: Ваша згода
  4. Передача даних: Дані не передаватимуться третім особам, за винятком юридичних зобов’язань.
  5. Зберігання даних: База даних, розміщена в мережі Occentus Networks (ЄС)
  6. Права: Ви можете будь-коли обмежити, відновити та видалити свою інформацію.

  1.   елав - сказав він

    Майстерно !!!

    1.    гексборг - сказав він

      Це не так погано, але велике спасибі. Сподіваюся, людям це сподобається. 🙂

      1.    Оскар - сказав він

        Мені це подобається ха!

        1.    гексборг - сказав він

          Тоді я, мабуть, зробив щось правильно. ЛОЛ!! 🙂

          Дякуємо за ваш коментар.

          1.    Блер Паскаль - сказав він

            Ебать, продовжуйте писати людину, так продовжуйте.

          2.    гексборг - сказав він

            @Blaire Pascal: Коментарі, подібні до вашого, заохочують це. 🙂 Щиро дякую !!

      2.    місто - сказав він

        Мені теж сподобалось ... дякую 🙂

        1.    гексборг - сказав він

          Дякую за коментар. Сподіваюся написати ще кілька. 🙂

  2.   мариан - сказав він

    Ваші дописи фантастичні, ви багато чому навчитеся, навпаки, навчитесь виконувати завдання елегантно та ефективно.

    Чи замислювались ви над тим, щоб зібрати всі ваші повідомлення про сценарії оболонки? Якщо відсортувати у форматі PDF, ви отримаєте чудове керівництво.

    Підбадьорюємось і велике спасибі!

    1.    гексборг - сказав він

      Дуже дякую!! Це не погана ідея. На даний момент їх лише два, але я подумаю про це пізніше. 🙂

  3.   Кійова - сказав він

    дуже хороша стаття, 5+.

    1.    гексборг - сказав він

      Дякую. Я рада, що тобі це подобається. 🙂

  4.   Себастьян - сказав він

    Відмінно! Мені потрібно змінити такий вираз, і я не знаю, як це зробити:
    192.168.0.138/ Сервер за 192.168.0.111/data
    Проблема полягає в символі "/".
    Я використовую команду:
    знайти. -назва "* .txt" -exec sed -i 's / TEXT1 / TEXT2 / g' {} \;
    Що використовується для виконання цього типу завдань з ремісією, але я не можу ...
    Хтось знає, як мені це робити?
    Обійми!
    Seba

    1.    гексборг - сказав він

      Що вам потрібно зробити, це уникнути персонажа таким чином:

      знайти. -name "* .txt" -exec sed -i 's / \ / Server / \ / data / g' {} \;

      Ви також можете використовувати інший сепаратор у sed. Це не повинен бути бар. Sed дозволяє використовувати будь-якого персонажа. Наприклад, це було б зрозуміліше:

      знайти. -назва "* .txt" -exec sed -i '| | Сервер | / дані | g' {} \;

      І якщо ви збираєтеся копіювати та вставляти команди з цього коментаря, будьте обережні з лапками, щоб wordpress міняв їх на друкарські. 🙂

      Привіт.

  5.   Себастьян - сказав він

    Відмінно !!!!
    Я давно шукав це рішення.
    Тут я залишаю повну команду, яку я використав

    знайти. -назва "* .txt" -exec sed -i 's | 192 \ .168 \ .0 \ .238 \ / Сервер | 192 \ .168 \ .0 \ .111 \ / data | g' {} \;

    Перевага цієї команди полягає в тому, що вона рекурсивно змінює всі файли .txt (або розширення, яке ви хочете) ... Ви повинні бути дуже обережними!
    Але це дуже корисно !!!

    Ну, дякую за все та тисячу привітань всій групі.
    Я їх завжди читаю з пошти!
    Обійми
    Seba