Find в linux регулярні вирази. Використання Grep і регулярних виразів для пошуку текстових шаблонів в Linux. Приклади використання регулярних виразів

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

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

Що таке регулярні вирази

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


На наш погляд навіть абсолютний новачок відразу зрозуміє, як вона влаштована і навіщо потрібно :) Якщо ж вам не цілком зрозуміло - просто читайте далі і все встане на свої місця.
Регулярний вираз - це шаблон, користуючись яким програми на кшталт sed або awk фільтрують тексти. У шаблонах використовуються звичайні ASCII-символи, що представляють самі себе, і так звані метасимволу, які відіграють особливу роль, наприклад, дозволяючи посилатися на якісь групи символів.

Типи регулярних виразів

Реалізації регулярних виразів в різних середовищах, наприклад, в мовах програмування на зразок Java, Perl і Python, в інструментах Linux на кшталт sed, awk і grep, мають певні особливості. Ці особливості залежать від так званих движків обробки регулярних виразів, які займаються інтерпретацією шаблонів.
У Linux є два движка регулярних виразів:
  • Движок, що підтримує стандарт POSIX Basic Regular Expression (BRE).
  • Движок, що підтримує стандарт POSIX Extended Regular Expression (ERE).
Більшість утиліт Linux відповідають, як мінімум, стандарту POSIX BRE, але деякі утиліти (в їх числі - sed) розуміють лише якесь підмножина стандарту BRE. Одна з причин такого обмеження - прагнення зробити такі утиліти як можна більш швидкими в справі обробки текстів.

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

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

Регулярні вирази POSIX BRE

Мабуть, найпростіший шаблон BRE є регулярний вираз для пошуку точного входження послідовності символів в тексті. Ось як виглядає пошук рядка в sed і awk:

$ Echo "This is a test" | sed -n "/ test / p" $ echo "This is a test" | awk "/ test / (print $ 0)"

Пошук тексту за шаблоном в sed


Пошук тексту за шаблоном в awk

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

Працюючи з регулярними виразами потрібно враховувати те, що вони чутливі до регістру символів:

$ Echo "This is a test" | awk "/ Test / (print $ 0)" $ echo "This is a test" | awk "/ test / (print $ 0)"

Регулярні вирази чутливі до регістру

Перше регулярне вираз збігів не знайшло, так як слово «test», що починається з великої літери, в тексті не зустрічається. Друге ж, налаштоване на пошук слова, написаного великими літерами, виявило в потоці відповідний рядок.

У регулярних виразах можна використовувати не тільки букви, але й прогалини, і цифри:

$ Echo "This is a test 2 again" | awk "/ test 2 / (print $ 0)"

Пошук фрагмента тексту, що містить прогалини і цифри

Прогалини сприймаються движком регулярних виразів як звичайні символи.

Спеціальні символи

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

.*^${}\+?|()
Якщо один з них потрібен в шаблоні, його потрібно буде екранувати за допомогою зворотної косої межі (зворотного слеша) - \.

Наприклад, якщо в тексті потрібно знайти знак долара, його треба включити в шаблон, випередивши символом екранування. Скажімо, є файл myfile з таким текстом:

There is 10 $ on my pocket
Знак долара можна виявити за допомогою такого шаблону:

$ Awk "/ \ $ / (print $ 0)" myfile

Використання в шаблоні спеціального символу

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

$ Echo "\ is a special character" | awk "/ \\ / (print $ 0)"

Екранування зворотного слеша

Хоча прямої слеш і не входить в наведений вище список спеціальних символів, спроба скористатися ним в регулярному виразі, написаному для sed або awk, призведе до помилки:

$ Echo "3/2" | awk "/// (print $ 0)"

Неправильне використання прямого слеша в шаблоні

Якщо він потрібен, його теж треба екранувати:

$ Echo "3/2" | awk "/ \ // (print $ 0)"

Екранування прямого слеша

якірні символи

Існують два спеціальних символу для прив'язки шаблона до початку або до кінця текстового рядка. Символ «кришка» - ^ дозволяє описувати послідовності символів, які знаходяться на початку текстових рядків. Якщо шуканий шаблон виявиться в іншому місці рядка, регулярний вираз на нього не відреагує. Виглядає використання цього символу так:

$ Echo "welcome to likegeeks website" | awk "/ ^ likegeeks / (print $ 0)" $ echo "likegeeks website" | awk "/ ^ likegeeks / (print $ 0)"

Пошук шаблону на початку рядка

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

$ Awk "/ ^ this / (print $ 0)" myfile


Пошук шаблону на початку рядка в тексті з файлу

При використанні sed, якщо помістити кришку де-небудь всередині шаблону, вона буде сприйматися як будь-який інший звичайний символ:

$ Echo "This ^ is a test" | sed -n "/ s ^ / p"

Кришка, що знаходиться не на початку шаблону в sed

У awk, при використанні такого ж шаблону, даний символ треба екранувати:

$ Echo "This ^ is a test" | awk "/ s \ ^ / (print $ 0)"

Кришка, що знаходиться не на початку шаблону в awk

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

У цьому нам допоможе знак долара - $, що є якірним символом кінця рядка:

$ Echo "This is a test" | awk "/ test $ / (print $ 0)"

Пошук тексту, що знаходиться в кінці рядка

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

$ Awk "/ ^ this is a test $ / (print $ 0)" myfile


Шаблон, в якому використані спеціальні символи початку і кінця рядка

Як видно, шаблон зреагував лише на рядок, яка повністю відповідає заданій послідовності символів і їх розташуванню.

Ось як, користуючись якірними символами, відфільтрувати порожні рядки:

$ Awk "! / ^ $ / (Print $ 0)" myfile
В даному шаблоні використовував символ заперечення, знак оклику -! . Завдяки використанню такого шаблону виконується пошук рядків, що не містять нічого між початком і кінцем рядка, а завдяки знаку оклику на друк виводяться лише рядки, які не відповідають цим шаблоном.

Символ «точка»

Точка використовується для пошуку будь-якого одиночного символу, за винятком символу перекладу рядка. Передамо такому регулярному виразу файл myfile, вміст якого наведено нижче:

$ Awk "/.st/(print $ 0)" myfile


Використання точки в регулярних виразах

Як видно з виведеним даними, шаблоном відповідають лише перші два рядки з файлу, так як вони містять послідовність символів «st», предварённую ще одним символом, в той час як третій рядок потрібній послідовності не містить, а в четвертій вона є, але знаходиться в самому початку рядка.

класи символів

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

Завдяки такому підходу можна організувати пошук будь-якого символу з заданого набору. Для опису класу символів використовуються квадратні дужки -:

$ Awk "/ th / (print $ 0)" myfile


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

Тут ми шукаємо послідовність символів «th», перед якою є символ «o» або символ «i».

Класи виявляються дуже до речі, якщо виконується пошук слів, які можуть починатися як з великої, так і з малої літери:

$ Echo "this is a test" | awk "/ his is a test / (print $ 0)" $ echo "This is a test" | awk "/ his is a test / (print $ 0)"

Пошук слів, які можуть починатися з малої або великої літери

Класи символів не обмежені літерами. Тут можна використовувати і інші символи. Не можна заздалегідь сказати, в якій ситуації знадобляться класи - все залежить від розв'язуваної задачі.

Заперечення класів символів

Класи символів можна використовувати і для вирішення завдання, зворотній описаної вище. А саме, замість пошуку символів, що входять в клас, можна організувати пошук за все, що в клас не входить. Для того, щоб добитися такої поведінки регулярного виразу, перед списком символів класу потрібно помістити знак ^. Виглядає це так:

$ Awk "/ [^ oi] th / (print $ 0)" myfile


Пошук символів, що не входять в клас

В даному випадку будуть знайдені послідовності символів «th», перед якими немає ні «o», ні «i».

діапазони символів

У символьних класах можна описувати діапазони символів, використовуючи тире:

$ Awk "/ st / (print $ 0)" myfile


Опис діапазону символів в символьному класі

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

Діапазони можна створювати і з чисел:

$ Echo "123" | awk "//" $ echo "12a" | awk "//"

Регулярний вираз для пошуку трьох будь-яких чисел

В клас символів можуть входити кілька діапазонів:

$ Awk "/ st / (print $ 0)" myfile


Клас символів, що складається з декількох діапазонів

Дане регулярний вираз знайде все послідовності «st», перед якими є символи з діапазонів a-f і m-z.

Спеціальні класи символів

У BRE є спеціальні класи символів, які можна використовувати при написанні регулярних виразів:
  • [[: Alpha:]] - відповідає будь-якому алфавітному символу, записаному в верхньому або нижньому регістрі.
  • [[: Alnum:]] - відповідає будь-якому алфавітно-цифровому символу, а саме - символам в діапазонах 0-9, A-Z, a-z.
  • [[: Blank:]] - відповідає пробілу і знаку табуляції.
  • [[: Digit:]] - будь-який цифровий символ від 0 до 9.
  • [[: Upper:]] - алфавітні символи в верхньому регістрі - A-Z.
  • [[: Lower:]] - алфавітні символи в нижньому регістрі - a-z.
  • [[: Print:]] - відповідає будь-якому друкується символу.
  • [[: Punct:]] - відповідає знаків пунктуації.
  • [[: Space:]] - пробільні символи, зокрема - пробіл, знак табуляції, символи NL, FF, VT, CR.
Використовувати спеціальні класи в шаблонах можна так:

$ Echo "abc" | awk "/ [[: alpha:]] / (print $ 0)" $ echo "abc" | awk "/ [[: digit:]] / (print $ 0)" $ echo "abc123" | awk "/ [[: digit:]] / (print $ 0)"


Спеціальні класи символів в регулярних виразах

Символ «зірочка»

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

$ Echo "test" | awk "/ tes * t / (print $ 0)" $ echo "tessst" | awk "/ tes * t / (print $ 0)"


Використання символу * в регулярних виразах

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

$ Echo "I like green color" | awk "/ colou * r / (print $ 0)" $ echo "I like green colour" | awk "/ colou * r / (print $ 0)"

Пошук слова, що має різні варіанти написання

У цьому прикладі одне і те ж регулярний вираз реагує і на слово «color», і на слово «colour». Це так завдяки тому, що символ «u», після якого стоїть зірочка, може або бути відсутнім, або зустрічатися кілька разів поспіль.

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

$ Awk "/this.*test/(print $ 0)" myfile


Шаблон, що реагує на будь-яку кількість будь-яких символів

В даному випадку неважливо скільки і яких символів знаходиться між словами «this» і «test».

Зірочку можна використовувати і з класами символів:

$ Echo "st" | awk "/ s * t / (print $ 0)" $ echo "sat" | awk "/ s * t / (print $ 0)" $ echo "set" | awk "/ s * t / (print $ 0)"


Використання зірочки з класами символів

У всіх трьох прикладах регулярний вираз спрацьовує, тому що зірочка після класу символів означає, що якщо буде знайдено будь-яку кількість символів «a» або «e», а також якщо їх знайти не вдасться, рядок буде відповідати заданим шаблоном.

Регулярні вирази POSIX ERE

Шаблони стандарту POSIX ERE, які підтримують деякі утиліти Linux, можуть містити додаткові символи. Як вже було сказано, awk підтримує цей стандарт, а ось sed - немає.

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

▍Вопросітельний знак

Знак питання вказує на те, що попередній символ може зустрітися в тексті один раз або не зустрітися зовсім. Цей символ - один з метасимволов повторень. Ось кілька прикладів:

$ Echo "tet" | awk "/ tes? t / (print $ 0)" $ echo "test" | awk "/ tes? t / (print $ 0)" $ echo "tesst" | awk "/ tes? t / (print $ 0)"


Знак питання в регулярних виразах

Як видно, в третьому випадку буква «s» зустрічається двічі, тому на слово «tesst» регулярний вираз не реагує.

Знак питання можна використовувати і з класами символів:

$ Echo "tst" | awk "/ t? st / (print $ 0)" $ echo "test" | awk "/ t? st / (print $ 0)" $ echo "tast" | awk "/ t? st / (print $ 0)" $ echo "taest" | awk "/ t? st / (print $ 0)" $ echo "teest" | awk "/ t? st / (print $ 0)"


Знак питання і класи символів

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

▍Сімвол «плюс»

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

$ Echo "test" | awk "/ te + st / (print $ 0)" $ echo "teest" | awk "/ te + st / (print $ 0)" $ echo "tst" | awk "/ te + st / (print $ 0)"


Символ «плюс» в регулярних виразах

В даному прикладі, якщо символу «e» в слові немає, движок регулярних виразів не знайдете в тексті відповідностей шаблоном. Символ «плюс» працює і з класами символів - цим він схожий на зірочку і знак питання:

$ Echo "tst" | awk "/ t + st / (print $ 0)" $ echo "test" | awk "/ t + st / (print $ 0)" $ echo "teast" | awk "/ t + st / (print $ 0)" $ echo "teeast" | awk "/ t + st / (print $ 0)"


Знак «плюс» і класи символів

В даному випадку якщо в рядку є будь-який символ з класу, текст буде визнаний відповідним шаблоном.

▍Фігурние дужки

Фігурні дужки, якими можна користуватися в ERE-шаблонах, схожі на символи, розглянуті вище, але вони дозволяють точніше ставити необхідну кількість входжень попереднього їм символу. Вказувати обмеження можна в двох форматах:
  • n - число, що задає точне число шуканих входжень
  • n, m - два числа, які трактуються так: «як мінімум n раз, але не більше ніж m».
Ось приклади першого варіанту:

$ Echo "tst" | awk "/ te (1) st / (print $ 0)" $ echo "test" | awk "/ te (1) st / (print $ 0)"

Фігурні дужки в шаблонах, пошук точного числа входжень

У старих версіях awk потрібно було використовувати ключ командного рядка --re-interval для того, щоб програма розпізнавала інтервали в регулярних виразах, але в нових версіях цього робити не потрібно.

$ Echo "tst" | awk "/ te (1,2) st / (print $ 0)" $ echo "test" | awk "/ te (1,2) st / (print $ 0)" $ echo "teest" | awk "/ te (1,2) st / (print $ 0)" $ echo "teeest" | awk "/ te (1,2) st / (print $ 0)"


Інтервал, заданий в фігурних дужках

В даному прикладі символ «e» повинен зустрітися в рядку 1 або 2 рази, тоді регулярний вираз відреагує на текст.

Фігурні дужки можна застосовувати і з класами символів. Тут діють вже знайомі вам принципи:

$ Echo "tst" | awk "/ t (1,2) st / (print $ 0)" $ echo "test" | awk "/ t (1,2) st / (print $ 0)" $ echo "teest" | awk "/ t (1,2) st / (print $ 0)" $ echo "teeast" | awk "/ t (1,2) st / (print $ 0)"


Фігурні дужки і класи символів

Шаблон відреагує на текст в тому випадку, якщо в ньому один або два рази зустрінеться символ «a» або символ «e».

▍Сімвол логічного «або»

символ | - вертикальна риса, означає в регулярних виразах логічне «або». Обробляючи регулярний вираз, що містить кілька фрагментів, розділених таким знаком, движок вважатиме аналізований текст відповідним в тому випадку, якщо він буде відповідати будь-якому з фрагментів. Ось приклад:

$ Echo "This is a test" | awk "/ test | exam / (print $ 0)" $ echo "This is an exam" | awk "/ test | exam / (print $ 0)" $ echo "This is something else" | awk "/ test | exam / (print $ 0)"


Логічне «або» в регулярних виразах

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

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

$ Echo "Like" | awk "/ Like (Geeks)? / (print $ 0)" $ echo "LikeGeeks" | awk "/ Like (Geeks)? / (print $ 0)"


Угруповання фрагментів регулярних виразів

У даних прикладах слово «Geeks» укладено в круглі дужки, після цієї конструкції йде знак питання. Нагадаємо, що знак питання означає «0 або 1 повторення», в результаті регулярний вираз відреагує і на рядок «Like», і на рядок «LikeGeeks».

практичні приклади

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

▍Подсчёт кількості файлів

Напишемо bash-скрипт, який підраховує файли, що знаходяться в директоріях, які записані в змінну оточення PATH. Для того, щоб це зробити, знадобиться, для початку, сформувати список шляхів для тек. Зробимо це за допомогою sed, замінивши двокрапки на прогалини:

$ Echo $ PATH | sed "s /: / / g"
Команда заміни підтримує регулярні вирази як шаблони для пошуку тексту. В даному випадку все гранично просто, шукаємо ми символ двокрапки, але ніхто не заважає використовувати тут і що-небудь інше - все залежить від конкретного завдання.
Тепер треба пройтися по отриманому списку в циклі і виконати там необхідні для підрахунку кількості файлів дії. Загальна схема скрипта буде такою:

Mypath = $ (echo $ PATH | sed "s /: / / g") for directory in $ mypath do done
Тепер напишемо повний текст скрипта, скориставшись командою ls для отримання відомостей про кількість файлів у кожній з директорій:

#! / Bin / bash mypath = $ (echo $ PATH | sed "s /: / / g") count = 0 for directory in $ mypath do check = $ (ls $ directory) for item in $ check do count = $ [$ count + 1] done echo "$ directory - $ count" count = 0 done
При запуску скрипта може виявитися, що деяких директорій з PATH не існує, однак, це не завадить йому порахувати файли в існуючих директоріях.


підрахунок файлів

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

▍Проверка адрес електронної пошти

Існують веб-сайти з величезними колекціями регулярних виразів, які дозволяють перевіряти адреси електронної пошти, номери телефонів, і так далі. Однак, одна справа - взяти готове, і зовсім інша - створити щось самому. Тому напишемо регулярний вираз для перевірки адрес електронної пошти. Почнемо з аналізу вихідних даних. Ось, наприклад, якийсь адреса:

[Email protected]
Ім'я користувача, username, може складатися з алфавітно-цифрових і деяких інших символів. А саме, це крапка, тире, символ підкреслення, знак «плюс». За ім'ям користувача слід знак @.

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

^(+)@
Це регулярний вираз можна прочитати так: «На початку рядка повинен бути як мінімум один символ з тих, які є в групі, заданої в квадратних дужках, а після цього повинен йти знак @».

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

(+)
Ім'я домену верхнього рівня підпорядковується особливими правилами. Тут можуть бути лише алфавітні символи, яких повинно бути не менше двох (наприклад, такі домени зазвичай містять код країни), і не більше п'яти. Все це означає, що шаблон для перевірки останньої частини адреси буде таким:

\.({2,5})$
Прочитати його можна так: «Спочатку повинна бути точка, потім - від 2 до 5 алфавітних символів, а після цього рядок закінчується».

Підготувавши шаблони для окремих частин регулярного виразу, зберемо їх разом:

^(+)@(+)\.({2,5})$
Тепер залишилося лише протестувати то, що вийшло:

$ Echo " [Email protected]"| Awk" /^(+)@(+)\.((2,5))$/(print $ 0) "$ echo" [Email protected]"| Awk" /^(+)@(+)\.((2,5))$/(print $ 0) "


Перевірка адреси електронної пошти за допомогою регулярних виразів

Те, що переданий awk текст виводиться на екран, означає, що система розпізнала в ньому адресу електронної пошти.

підсумки

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

У цій серії матеріалів ми зазвичай показували дуже прості приклади bash-скриптів, які складалися буквально з кількох рядків. Наступного разу розглянемо дещо масштабніше.

Шановні читачі! А ви користуєтеся регулярними виразами при обробці текстів в сценаріях командного рядка?

Про це самовчителі

Ласкаво просимо в «Ази адміністрування», друге з чотирьох навчальних посібників, розроблених щоб підготувати вас до іспиту 101 в Linux Professional Institute. У цій частині ми розглянемо як використовувати регулярні вирази для пошуку тексту в файлах по шаблонах. Потім, ви познайомитеся з «Стандартом ієрархії файлової системи» (Filesystem Hierarchy Standard або скор. FHS), також ми покажемо вам як знаходити потрібні файли у вашій системі. Після чого, ви дізнаєтеся як отримати повний контроль над процесами в Linux, запускаючи їх у фоновому режимі, переглядаючи список процесів, отсоединяя їх від терміналу, і багато іншого. Далі піде швидке введення в конвеєри, перенаправлення і команди обробки тексту. І нарешті, ми познайомимо вас з модулями ядра Linux.

Зокрема ця частина самовчителя (Частина 2) ідеальна для тих, хто вже має непогані базові знання bash і хоче отримати якісне введення в основні завдання адміністрування Linux. Якщо в Linux ви новачок, ми рекомендуємо вам спершу закінчити першу частину цієї серії практичних посібників. Для деяких, велика частина даного матеріалу буде нової, більш досвідчені ж користувачі Linux можуть вважати його відмінним засобом підвести підсумок своїм базовим навичкам адміністрування.



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

Регулярні вирази

Що таке «регулярний вираз»?

Регулярний вираз (по англ. Regular expression, скор. «Regexp» або «regex», в вітчизні іноді зветься «регулярки» - прим. Пер.) - це особливий синтаксис використовується для опису текстових шаблонів. В Linux-системах регулярні вирази широко використовуються для пошуку в тексті за шаблоном, а також для операцій пошуку і заміни на текстових потоках.

У порівнянні з глоббінгом

Як тільки ми почнемо розглядати регулярні вирази, можливо ви зверніть увагу, що їх синтаксис дуже схожий на синтаксис підстановки імен файлів (globbing), який ми розглядали в першій частині. Однак, не варто плекати ілюзій, ця схожість дуже поверхнева. Регулярні вирази і глоббінг-шаблони, навіть коли вони виглядають схоже, принципово різні речі.

проста подстрока

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

$ grep bash / etc / passwd
operator: x: 11: 0: operator: / root: / bin / bash root: x: 0: 0 :: / root: / bin / bash ftp: x: 40: 1 :: / home / ftp: / bin / bash

Вище, перший параметр для grep, це regex; другий - ім'я файлу. grep зчитував кожен рядок з / Etc / passwdі прикладав на неї просту regex-подстроку «bash» в пошуках збіги. Якщо збіг виявлялося, то grep виводив весь рядок цілком; в іншому випадку, рядок ігнорувалася.

Розуміння простий подстроки

У загальному випадку, якщо ви шукайте подстроку, ви просто можете вказати її буквально, не використовуючи будь-яких «спеціальних» символів. Вам знадобитися особливо подбати, тільки якщо ваша подстрока містить +,., *, [,] Або \, в цьому випадку ці символи повинні бути екрановані зворотною слешем, а подстрока полягати в лапки. Ось кілька прикладів регулярних виразів у вигляді простої підрядка:

  • / Tmp (пошук рядка / tmp)
  • "\" (Пошук рядка)
  • "\ * Funny \ *" (пошук рядка * funny *)
  • «Ld \ .so» (пошук рядка ld.so)

метасимволи

За допомогою регулярних виразів використовуючи метасимволи можливо здійснювати набагато складніший пошук, ніж в прикладах, які недавно розглядали. Один з таких метасимволов "." (Точка), який збігається з будь-яким одиничним символом:

$ grep dev.sda / etc / fstab
/ Dev / sda3 / reiserfs noatime, ro 1 + 1 / dev / sda1 / boot reiserfs noauto, noatime, notail 1 2 / dev / sda2 swap swap sw 0 0 # / dev / sda4 / mnt / extra reiserfs noatime, rw 1 + 1

У цьому прикладі текст dev.sda не виникає буквально ні в одній з рядків з / Etc / fstab. Однак, grep сканує його не буквальне по рядку dev.sda, а по dev.sda шаблоном. Запам'ятайте, що "." буде відповідати будь-якому одиничному символу. Як ви бачите, метасимвол "." функціонально еквівалентний тому, як працює метасимвол "?" в glob-підстановках.

Використання

Якщо ми хочемо задати символ конкретніше, ніж це робить ".", То можемо використовувати [і] (квадратні дужки), щоб вказати підмножину символів для порівняння:

$ grep dev.sda / etc / fstab
/ Dev / sda1 / boot reiserfs noauto, noatime, notail 1 2 / dev / sda2 swap swap sw 0 0

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

Використання [^]

Ви можете звернути значення квадратних дужок помістивши ^ відразу після [. В цьому випадку дужки будуть відповідати будь-якому символу який НЕ перераховано всередині них. І знову, зауважте що [^] ми використовуємо з регулярними виразом, а [!] З glob:

$ grep dev.hda [^ 12] / etc / fstab
/ Dev / hda3 / reiserfs noatime, ro 1 + 1 # / dev / hda4 / mnt / extra reiserfs noatime, rw 1 + 1

відрізняється синтаксис

Дуже важливо відзначити, що синтаксис всередині квадратних дужок докорінно відрізняється від решти регулярного виразу. Наприклад, якщо ви помістіть "." всередину квадратних дужок, це дозволить квадратним дужках збігатися з "." буквально, також як 1 і 2 в прикладі вище. Для порівняння, "." вміщена поза квадратних дужок, буде інтерпретована як метасимвол, якщо не приставити "\". Ми можемо отримати вигоду з цього факту для виведення рядків з / etc / fstab які містять рядок dev.sda, як вона записана:

$ grep dev [.] sda / etc / fstab

Також, ми могли б набрати:

$ grep "dev \ .sda" / etc / fstab

Ці регулярні вирази ймовірно не задовольняють ні одному рядку з вашого / Etc / fstabфайлу.

Матасімвол *

Деякі метасимволу самі по собі не відповідають нічому, але змінюють значення попереднього символу. Один з таких символів, це * (зірочка), який використовується для зіставлення нульового або більшій кількості повторень попереднього символу. Зауважте, це означає, що * має інше значення в регулярки, ніж в глоббінге. Ось кілька прикладів, і зверніть особливу увагу на ті випадки де зіставлення регулярних виразів відрізняється від glob-підстановок:

  • ab * cзбігається з «abbbbc», але не з «abqc» (в разі glob-підстановки, обидві рядки будуть задовольняти шаблоном. Ви вже зрозуміли чому?)
  • ab * cзбігається з «abc», але не з «abbqbbc» (знову ж, при glob-підстановці, шаблон можна порівняти з обома рядками)
  • ab * cзбігається з «ac», але не з «cba» (в разі глоббінга, ні «ac», ні «cba» не задовольняють шаблоном)
  • b * eзбігається з «bqe» і з «be» (glob-підстановці задовольняє «bqe», але не «be»)
  • b * eзбігається з «bccqqe», але не з «bccc» (при глоббінге шаблон точно так же співпаде з першим, але не з другим)
  • b * eзбігається з «bqqcce», але не з «cqe» (так само і при glob-підстановці)
  • b * eзадовольняє «bbbeee» (але не у випадку глоббінга)
  • .* можна порівняти з будь-рядком (glob-підстановці задовольняють лише рядки починаються з ".")
  • foo. *співпаде з будь-підрядком починається з «foo» (в разі glob-підстановки цей шаблон буде збігатися з рядками, які починаються часткою з чотирьох символів «foo.»)

Отже, повторимо для закріплення: рядок «ac» підходить під регулярний вираз «ab * c» тому, що зірочка також дозволяє повторення попереднього виразу (b) нуль раз. І знову, цінно відзначити для себе, що метасимвол * в регулярки інтерпретується зовсім інакше, ніж символ * в glob-подстновках.

Початок і кінець рядка

Останні метасимволу, що ми детально розглянемо, це ^ і $, які використовуються для сопостовленія початку і кінця рядку, відповідно. Скориставшись ^ на початку вашого regex, ви «прикріпіть» ваш шаблон до початку рядка. У следующии прикладі, ми використовуємо регулярний вираз ^ #, яке задовольняє будь-якому рядку що починається з символу #:

$ grep ^ # / etc / fstab

#

Полнострочние регулярки

^ І $ можна комбінувати, для зіставлень з усією рядком цілком. Наприклад, нижченаведена регулярка буде відповідати рядкам починається з символу #, а закінчується символом ".", При довільній кількості символів між ними:

$ grep "^ #. * \. $" / etc / fstab
# / Etc / fstab: static file system information.

В наведеному вище прикладі ми уклали наше регулярний вираз в поодинокі лапки, щоб запобігти інтерпретування символу $ командною оболонкою. Без одиночних лапок $ зник би з нашої регулярки ще навіть до того, як grep міг його побачити.

про авторів

Daniel Robbins

Деніель Роббінс - засновник спільноти Gentoo і творець операційної системи Gentoo Linux. Деніель проживає в Нью-Мехіко зі свій дружиною Мері і двома енергійними дочками. Він також засновник і глава Funtoo, написав безліч технічних статей для IBM developerWorks, Intel Developer Services і C / C ++ Users Journal.

Chris Houser

Кріс Хаусер був прихильником UNIX c 1994 року, коли приєднався до команди адміністраторів університету Тейлора (Індіана, США), де отримав ступінь бакалавра в комп'ютерних науках і математиці. Після він працював у безлічі областей, включаючи веб-додатки, редагування відео, драйвера для UNIX і криптографічний захист. На даний момент працює в Sentry Data Systems. Кріс також зробив внесок у безліч вільних проектів, таких як Gentoo Linux і Clojure, став співавтором книги The Joy of Clojure.

Aron Griffis

Ейрон Гриффис живе на території Бостона, де провів останнє десятиліття працюючи в Hewlett-Packard над такими проектами, як мережеві UNIX-драйвера для Tru64, сертифікація безпеки Linux, Xen та KVM віртуалізація, і найостанніше - платформа HP ePrint. У вільний від програмування час Ейрон воліє размищлять над проблемами програмування катаючись на своєму велосипеді, жонглюючи битами, або вболіваючи за бостонську професійну бейсбольну команду «Червоні Шкарпетки».

grep розшифровується як 'global regular expression printer'. grep відрізає потрібні вам рядки з текстових файлів які містять вказаний користувачем текст.

grep може бути використаний двома шляхами - сам по собі або в комбінації з потоками.

grep дуже великий в функціональності, за рахунок великої кількості підтримуваних їм опцій, таких як: пошук з використанням строкового шаблону або RegExpрегулярних виразів шаблон або perl based регулярних виразів і т.д.

Через його різних функціональних можливостей інструмент grep має безліч варіантів, включаючи egrep (Extended GREP), fgrep (Fixed GREP), pgrep (Process GREP), rgrep (рекурсивний GREP)і т.д. Але ці варіанти мають незначні відмінності від оригінального grep.

параметри grep

$ Grep -V grep (GNU grep) 2.10 Copyright (C) 2011 Free Software Foundation, Inc. Ліцензія GPLv3 +

Існують модифікації утиліти grep: egrep (з обробкою розширених регулярних виразів), fgrep (трактує символи $ * ^ | () \ як літерали, тобто буквально), rgrep (з включеним рекурсивним пошуком).

    egrep те ж саме що grep -E

    fgrep те ж саме що grep -F

    rgrep те ж саме що grep -r

    grep [-b] [-c] [-i] [-l] [-n] [-s] [-v] ограніченное_регулярное_вираженіе_BRE [файл ...]

Команда grep зіставляє рядки вихідних файлів з шаблоном, заданим ограніченним_регулярним_вираженіем. Якщо файли не вказані, використовується стандартне введення. Зазвичай кожна успішно зіставлена ​​рядок копіюється на стандартний висновок; якщо вихідних файлів кілька, перед знайденої рядком видається ім'я файлу. У grep використовується компактний недетермінований алгоритм. Як шаблонів сприймаються обмежені регулярні вирази (вирази, що мають своїми значеннями ланцюжка символів, і використовують обмежений набір алфавітно-цифрових і спеціальних символів). Вони мають той же сенс, що і регулярні вирази в ed.

Для екранування символів $, *,, ^, |, (), і \ від інтерпретації shell "ом найпростіше укладати ограніченное_регулярное_вираженіе в одинарні лапки.

Опції:

B Передує кожен рядок номером блоку, в якому вона була знайдена. Це може стати в нагоді при пошуку блоків по контексту (блоки нумеруються з 0). -c Видає тільки кількість рядків, що містять зразок. -h Запобігає видачу імені файлу, що містить зіставити рядок, перед власне рядком. Використовується при пошуку по декількох файлах. -i Ігнорує регістр символів при порівняннях. -l Видає тільки імена файлів, що містять зіставити рядки, по одному в рядку. Якщо зразок знайдений в декількох рядках файлу, ім'я файлу не повторюється. -n Видає перед кожним рядком її номер у файлі (рядки нумеруються з 1). -s Пригнічує видачу повідомлень про що не існують або недоступних для читання файлах. -v Видає всі рядки, за винятком містять зразок. -w Шукає вираз як слово, як якщо б воно було оточене метасимвол \< и \>.

grep --help

Використання: grep [ПАРАМЕТР] ... ШАБЛОН [Фото] ... Пошук шаблонів в кожному ФАЙЛІ або в стандартному вводі. За замовчуванням, ШАБЛОН є просте регулярний вираз (BRE). Приклад: grep -i "hello world" menu.h main.c Вибір типу регулярного виразу і його інтерпретація: -E, --extended-regexp ШАБЛОН - розширене регулярний вираз (ERE) -F, --fixed-regexp ШАБЛОН - рядки фіксованої довжини, розділені символом нового рядка -G, --basic-regexp ШАБЛОН - просте регулярний вираз (BRE) -P, --perl-regexp ШАБЛОН - регулярне вираження мови Perl -e, --regexp = ШАБЛОН використовувати ШАБЛОН для пошуку - f, --file = Фото брати ШАБЛОН з файлами -i, --ignore-case ігнорувати відмінність регістра -w, --word-regexp ШАБЛОН повинен підходити до всіх слів -x, --line-regexp ШАБЛОН повинен підходити до всієї рядку -z, --null-data рядки поділяються байтом з нульовим значенням, а не символом кінця рядка Різне: -s, --no-messages пригнічувати повідомлення про помилки -v, --revert-match вибирати не підходять рядки -V, - -version надрукувати інформацію про версію і вийти --help показати цю довідку і закінчити роботу --mmap для забезпечення сумісності, ігнорується Управле ня висновком: -m, --max-count = ЧИСЛО зупинитися після зазначеного ЧИСЛА збігів -b, --byte-offset друкувати разом з вихідними рядками зміщення в байтах -n, --line-number друкувати номер рядка разом з вихідними рядками - -line-buffered скидати буфер після кожного рядка -H, --with-filename друкувати ім'я файлу для кожного збігу -h, --no-filename не починати висновок з імені файлу --label = МЕТКА використовувати МІТКУ в якості імені файлу для стандартного введення -o, --only-matching показувати лише частину рядка, що збігається з шаблоном -q, --quiet, --silent пригнічувати весь звичайний висновок --binary-files = ТИП вважати, що двійковий файл має ТИП: binary, text або without-match. -a, --text той же що і --binary-files = text -I той же, що і --binary-files = without-match -d, --directories = дії як обробляти каталоги ДІЯ може бути read (читати ), recurse (рекурсивно) або skip (пропускати). -D, --devices = дії як обробляти пристрої, FIFO і сокети ДІЯ може бути read або skip -R, -r, --recursive той же, що і --directories = recurse --include = Ф_ШАБЛОН обробити тільки файли, які підпадають під Ф_ШАБЛОН --exclude = Ф_ШАБЛОН пропустити файли і каталоги, які підпадають під Ф_ШАБЛОН --exclude-from = ФАЙЛ пропустити файли, які підпадають під шаблон файлів з ФАЙЛА --exclude-dir = шАБЛОН каталоги, які підпадають під шАБЛОН, будуть пропущені -L, - -files-without-match друкувати лише імена Фото без збігів -l, --files-with-matches друкувати лише імена Фото з збігами -c, --count друкувати тільки кількість співпадаючих рядків на Фото -T, --initial-tab вирівнювати табуляцією (якщо потрібно) -Z, --null друкувати байт 0 після імені ФАЙЛА Управління контекстом: -B, --before-context = ЧИС друкувати ЧИСЛО рядків попереднього контексту -A, --after-context = ЧИС друкувати ЧИСЛО рядків подальшого контексту -C, --context [= ЧИС] друкувати ЧИСЛО рядків контексту число той же, що і - -context = ЧИСЛО --color [= КОЛИ], --colour [= КОЛИ] використовувати маркери для відмінності співпадаючих рядків; КОЛИ може бути always (завжди), never (ніколи) або auto (автоматично) -U, --binary не видаляти символи CR в кінці рядка (MSDOS) -u, --unix-byte-offsets видавати зміщення, как-будто немає CR-ів (MSDOS) Замість «egrep» передбачається запуск «grep -E». Замість «fgrep» передбачається «grep -F». Запуск під іменами «egrep» або «fgrep» краще не виконувати. Коли не заданий Фото, або коли Фото це -, то читається стандартний ввід. Якщо вказано менше, ніж два файли, то передбачає -h. При знаходженні збігів кодом завершення програми буде 0, і 1, якщо нет.Прі виникненні помилок, або якщо не вказано параметр -q, кодом завершення буде 2. Про помилки повідомляйте за адресою Про помилки в перекладі повідомляйте за адресою Домашня сторінка GNU Grep: Довідка по роботі з програмами GNU:

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

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

Що таке регулярні вирази

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


На наш погляд навіть абсолютний новачок відразу зрозуміє, як вона влаштована і навіщо потрібно :) Якщо ж вам не цілком зрозуміло - просто читайте далі і все встане на свої місця.
Регулярний вираз - це шаблон, користуючись яким програми на кшталт sed або awk фільтрують тексти. У шаблонах використовуються звичайні ASCII-символи, що представляють самі себе, і так звані метасимволу, які відіграють особливу роль, наприклад, дозволяючи посилатися на якісь групи символів.

Типи регулярних виразів

Реалізації регулярних виразів в різних середовищах, наприклад, в мовах програмування на зразок Java, Perl і Python, в інструментах Linux на кшталт sed, awk і grep, мають певні особливості. Ці особливості залежать від так званих движків обробки регулярних виразів, які займаються інтерпретацією шаблонів.
У Linux є два движка регулярних виразів:
  • Движок, що підтримує стандарт POSIX Basic Regular Expression (BRE).
  • Движок, що підтримує стандарт POSIX Extended Regular Expression (ERE).
Більшість утиліт Linux відповідають, як мінімум, стандарту POSIX BRE, але деякі утиліти (в їх числі - sed) розуміють лише якесь підмножина стандарту BRE. Одна з причин такого обмеження - прагнення зробити такі утиліти як можна більш швидкими в справі обробки текстів.

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

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

Регулярні вирази POSIX BRE

Мабуть, найпростіший шаблон BRE є регулярний вираз для пошуку точного входження послідовності символів в тексті. Ось як виглядає пошук рядка в sed і awk:

$ Echo "This is a test" | sed -n "/ test / p" $ echo "This is a test" | awk "/ test / (print $ 0)"

Пошук тексту за шаблоном в sed


Пошук тексту за шаблоном в awk

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

Працюючи з регулярними виразами потрібно враховувати те, що вони чутливі до регістру символів:

$ Echo "This is a test" | awk "/ Test / (print $ 0)" $ echo "This is a test" | awk "/ test / (print $ 0)"

Регулярні вирази чутливі до регістру

Перше регулярне вираз збігів не знайшло, так як слово «test», що починається з великої літери, в тексті не зустрічається. Друге ж, налаштоване на пошук слова, написаного великими літерами, виявило в потоці відповідний рядок.

У регулярних виразах можна використовувати не тільки букви, але й прогалини, і цифри:

$ Echo "This is a test 2 again" | awk "/ test 2 / (print $ 0)"

Пошук фрагмента тексту, що містить прогалини і цифри

Прогалини сприймаються движком регулярних виразів як звичайні символи.

Спеціальні символи

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

.*^${}\+?|()
Якщо один з них потрібен в шаблоні, його потрібно буде екранувати за допомогою зворотної косої межі (зворотного слеша) - \.

Наприклад, якщо в тексті потрібно знайти знак долара, його треба включити в шаблон, випередивши символом екранування. Скажімо, є файл myfile з таким текстом:

There is 10 $ on my pocket
Знак долара можна виявити за допомогою такого шаблону:

$ Awk "/ \ $ / (print $ 0)" myfile

Використання в шаблоні спеціального символу

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

$ Echo "\ is a special character" | awk "/ \\ / (print $ 0)"

Екранування зворотного слеша

Хоча прямої слеш і не входить в наведений вище список спеціальних символів, спроба скористатися ним в регулярному виразі, написаному для sed або awk, призведе до помилки:

$ Echo "3/2" | awk "/// (print $ 0)"

Неправильне використання прямого слеша в шаблоні

Якщо він потрібен, його теж треба екранувати:

$ Echo "3/2" | awk "/ \ // (print $ 0)"

Екранування прямого слеша

якірні символи

Існують два спеціальних символу для прив'язки шаблона до початку або до кінця текстового рядка. Символ «кришка» - ^ дозволяє описувати послідовності символів, які знаходяться на початку текстових рядків. Якщо шуканий шаблон виявиться в іншому місці рядка, регулярний вираз на нього не відреагує. Виглядає використання цього символу так:

$ Echo "welcome to likegeeks website" | awk "/ ^ likegeeks / (print $ 0)" $ echo "likegeeks website" | awk "/ ^ likegeeks / (print $ 0)"

Пошук шаблону на початку рядка

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

$ Awk "/ ^ this / (print $ 0)" myfile


Пошук шаблону на початку рядка в тексті з файлу

При використанні sed, якщо помістити кришку де-небудь всередині шаблону, вона буде сприйматися як будь-який інший звичайний символ:

$ Echo "This ^ is a test" | sed -n "/ s ^ / p"

Кришка, що знаходиться не на початку шаблону в sed

У awk, при використанні такого ж шаблону, даний символ треба екранувати:

$ Echo "This ^ is a test" | awk "/ s \ ^ / (print $ 0)"

Кришка, що знаходиться не на початку шаблону в awk

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

У цьому нам допоможе знак долара - $, що є якірним символом кінця рядка:

$ Echo "This is a test" | awk "/ test $ / (print $ 0)"

Пошук тексту, що знаходиться в кінці рядка

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

$ Awk "/ ^ this is a test $ / (print $ 0)" myfile


Шаблон, в якому використані спеціальні символи початку і кінця рядка

Як видно, шаблон зреагував лише на рядок, яка повністю відповідає заданій послідовності символів і їх розташуванню.

Ось як, користуючись якірними символами, відфільтрувати порожні рядки:

$ Awk "! / ^ $ / (Print $ 0)" myfile
В даному шаблоні використовував символ заперечення, знак оклику -! . Завдяки використанню такого шаблону виконується пошук рядків, що не містять нічого між початком і кінцем рядка, а завдяки знаку оклику на друк виводяться лише рядки, які не відповідають цим шаблоном.

Символ «точка»

Точка використовується для пошуку будь-якого одиночного символу, за винятком символу перекладу рядка. Передамо такому регулярному виразу файл myfile, вміст якого наведено нижче:

$ Awk "/.st/(print $ 0)" myfile


Використання точки в регулярних виразах

Як видно з виведеним даними, шаблоном відповідають лише перші два рядки з файлу, так як вони містять послідовність символів «st», предварённую ще одним символом, в той час як третій рядок потрібній послідовності не містить, а в четвертій вона є, але знаходиться в самому початку рядка.

класи символів

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

Завдяки такому підходу можна організувати пошук будь-якого символу з заданого набору. Для опису класу символів використовуються квадратні дужки -:

$ Awk "/ th / (print $ 0)" myfile


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

Тут ми шукаємо послідовність символів «th», перед якою є символ «o» або символ «i».

Класи виявляються дуже до речі, якщо виконується пошук слів, які можуть починатися як з великої, так і з малої літери:

$ Echo "this is a test" | awk "/ his is a test / (print $ 0)" $ echo "This is a test" | awk "/ his is a test / (print $ 0)"

Пошук слів, які можуть починатися з малої або великої літери

Класи символів не обмежені літерами. Тут можна використовувати і інші символи. Не можна заздалегідь сказати, в якій ситуації знадобляться класи - все залежить від розв'язуваної задачі.

Заперечення класів символів

Класи символів можна використовувати і для вирішення завдання, зворотній описаної вище. А саме, замість пошуку символів, що входять в клас, можна організувати пошук за все, що в клас не входить. Для того, щоб добитися такої поведінки регулярного виразу, перед списком символів класу потрібно помістити знак ^. Виглядає це так:

$ Awk "/ [^ oi] th / (print $ 0)" myfile


Пошук символів, що не входять в клас

В даному випадку будуть знайдені послідовності символів «th», перед якими немає ні «o», ні «i».

діапазони символів

У символьних класах можна описувати діапазони символів, використовуючи тире:

$ Awk "/ st / (print $ 0)" myfile


Опис діапазону символів в символьному класі

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

Діапазони можна створювати і з чисел:

$ Echo "123" | awk "//" $ echo "12a" | awk "//"

Регулярний вираз для пошуку трьох будь-яких чисел

В клас символів можуть входити кілька діапазонів:

$ Awk "/ st / (print $ 0)" myfile


Клас символів, що складається з декількох діапазонів

Дане регулярний вираз знайде все послідовності «st», перед якими є символи з діапазонів a-f і m-z.

Спеціальні класи символів

У BRE є спеціальні класи символів, які можна використовувати при написанні регулярних виразів:
  • [[: Alpha:]] - відповідає будь-якому алфавітному символу, записаному в верхньому або нижньому регістрі.
  • [[: Alnum:]] - відповідає будь-якому алфавітно-цифровому символу, а саме - символам в діапазонах 0-9, A-Z, a-z.
  • [[: Blank:]] - відповідає пробілу і знаку табуляції.
  • [[: Digit:]] - будь-який цифровий символ від 0 до 9.
  • [[: Upper:]] - алфавітні символи в верхньому регістрі - A-Z.
  • [[: Lower:]] - алфавітні символи в нижньому регістрі - a-z.
  • [[: Print:]] - відповідає будь-якому друкується символу.
  • [[: Punct:]] - відповідає знаків пунктуації.
  • [[: Space:]] - пробільні символи, зокрема - пробіл, знак табуляції, символи NL, FF, VT, CR.
Використовувати спеціальні класи в шаблонах можна так:

$ Echo "abc" | awk "/ [[: alpha:]] / (print $ 0)" $ echo "abc" | awk "/ [[: digit:]] / (print $ 0)" $ echo "abc123" | awk "/ [[: digit:]] / (print $ 0)"


Спеціальні класи символів в регулярних виразах

Символ «зірочка»

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

$ Echo "test" | awk "/ tes * t / (print $ 0)" $ echo "tessst" | awk "/ tes * t / (print $ 0)"


Використання символу * в регулярних виразах

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

$ Echo "I like green color" | awk "/ colou * r / (print $ 0)" $ echo "I like green colour" | awk "/ colou * r / (print $ 0)"

Пошук слова, що має різні варіанти написання

У цьому прикладі одне і те ж регулярний вираз реагує і на слово «color», і на слово «colour». Це так завдяки тому, що символ «u», після якого стоїть зірочка, може або бути відсутнім, або зустрічатися кілька разів поспіль.

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

$ Awk "/this.*test/(print $ 0)" myfile


Шаблон, що реагує на будь-яку кількість будь-яких символів

В даному випадку неважливо скільки і яких символів знаходиться між словами «this» і «test».

Зірочку можна використовувати і з класами символів:

$ Echo "st" | awk "/ s * t / (print $ 0)" $ echo "sat" | awk "/ s * t / (print $ 0)" $ echo "set" | awk "/ s * t / (print $ 0)"


Використання зірочки з класами символів

У всіх трьох прикладах регулярний вираз спрацьовує, тому що зірочка після класу символів означає, що якщо буде знайдено будь-яку кількість символів «a» або «e», а також якщо їх знайти не вдасться, рядок буде відповідати заданим шаблоном.

Регулярні вирази POSIX ERE

Шаблони стандарту POSIX ERE, які підтримують деякі утиліти Linux, можуть містити додаткові символи. Як вже було сказано, awk підтримує цей стандарт, а ось sed - немає.

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

▍Вопросітельний знак

Знак питання вказує на те, що попередній символ може зустрітися в тексті один раз або не зустрітися зовсім. Цей символ - один з метасимволов повторень. Ось кілька прикладів:

$ Echo "tet" | awk "/ tes? t / (print $ 0)" $ echo "test" | awk "/ tes? t / (print $ 0)" $ echo "tesst" | awk "/ tes? t / (print $ 0)"


Знак питання в регулярних виразах

Як видно, в третьому випадку буква «s» зустрічається двічі, тому на слово «tesst» регулярний вираз не реагує.

Знак питання можна використовувати і з класами символів:

$ Echo "tst" | awk "/ t? st / (print $ 0)" $ echo "test" | awk "/ t? st / (print $ 0)" $ echo "tast" | awk "/ t? st / (print $ 0)" $ echo "taest" | awk "/ t? st / (print $ 0)" $ echo "teest" | awk "/ t? st / (print $ 0)"


Знак питання і класи символів

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

▍Сімвол «плюс»

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

$ Echo "test" | awk "/ te + st / (print $ 0)" $ echo "teest" | awk "/ te + st / (print $ 0)" $ echo "tst" | awk "/ te + st / (print $ 0)"


Символ «плюс» в регулярних виразах

В даному прикладі, якщо символу «e» в слові немає, движок регулярних виразів не знайдете в тексті відповідностей шаблоном. Символ «плюс» працює і з класами символів - цим він схожий на зірочку і знак питання:

$ Echo "tst" | awk "/ t + st / (print $ 0)" $ echo "test" | awk "/ t + st / (print $ 0)" $ echo "teast" | awk "/ t + st / (print $ 0)" $ echo "teeast" | awk "/ t + st / (print $ 0)"


Знак «плюс» і класи символів

В даному випадку якщо в рядку є будь-який символ з класу, текст буде визнаний відповідним шаблоном.

▍Фігурние дужки

Фігурні дужки, якими можна користуватися в ERE-шаблонах, схожі на символи, розглянуті вище, але вони дозволяють точніше ставити необхідну кількість входжень попереднього їм символу. Вказувати обмеження можна в двох форматах:
  • n - число, що задає точне число шуканих входжень
  • n, m - два числа, які трактуються так: «як мінімум n раз, але не більше ніж m».
Ось приклади першого варіанту:

$ Echo "tst" | awk "/ te (1) st / (print $ 0)" $ echo "test" | awk "/ te (1) st / (print $ 0)"

Фігурні дужки в шаблонах, пошук точного числа входжень

У старих версіях awk потрібно було використовувати ключ командного рядка --re-interval для того, щоб програма розпізнавала інтервали в регулярних виразах, але в нових версіях цього робити не потрібно.

$ Echo "tst" | awk "/ te (1,2) st / (print $ 0)" $ echo "test" | awk "/ te (1,2) st / (print $ 0)" $ echo "teest" | awk "/ te (1,2) st / (print $ 0)" $ echo "teeest" | awk "/ te (1,2) st / (print $ 0)"


Інтервал, заданий в фігурних дужках

В даному прикладі символ «e» повинен зустрітися в рядку 1 або 2 рази, тоді регулярний вираз відреагує на текст.

Фігурні дужки можна застосовувати і з класами символів. Тут діють вже знайомі вам принципи:

$ Echo "tst" | awk "/ t (1,2) st / (print $ 0)" $ echo "test" | awk "/ t (1,2) st / (print $ 0)" $ echo "teest" | awk "/ t (1,2) st / (print $ 0)" $ echo "teeast" | awk "/ t (1,2) st / (print $ 0)"


Фігурні дужки і класи символів

Шаблон відреагує на текст в тому випадку, якщо в ньому один або два рази зустрінеться символ «a» або символ «e».

▍Сімвол логічного «або»

символ | - вертикальна риса, означає в регулярних виразах логічне «або». Обробляючи регулярний вираз, що містить кілька фрагментів, розділених таким знаком, движок вважатиме аналізований текст відповідним в тому випадку, якщо він буде відповідати будь-якому з фрагментів. Ось приклад:

$ Echo "This is a test" | awk "/ test | exam / (print $ 0)" $ echo "This is an exam" | awk "/ test | exam / (print $ 0)" $ echo "This is something else" | awk "/ test | exam / (print $ 0)"


Логічне «або» в регулярних виразах

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

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

$ Echo "Like" | awk "/ Like (Geeks)? / (print $ 0)" $ echo "LikeGeeks" | awk "/ Like (Geeks)? / (print $ 0)"


Угруповання фрагментів регулярних виразів

У даних прикладах слово «Geeks» укладено в круглі дужки, після цієї конструкції йде знак питання. Нагадаємо, що знак питання означає «0 або 1 повторення», в результаті регулярний вираз відреагує і на рядок «Like», і на рядок «LikeGeeks».

практичні приклади

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

▍Подсчёт кількості файлів

Напишемо bash-скрипт, який підраховує файли, що знаходяться в директоріях, які записані в змінну оточення PATH. Для того, щоб це зробити, знадобиться, для початку, сформувати список шляхів для тек. Зробимо це за допомогою sed, замінивши двокрапки на прогалини:

$ Echo $ PATH | sed "s /: / / g"
Команда заміни підтримує регулярні вирази як шаблони для пошуку тексту. В даному випадку все гранично просто, шукаємо ми символ двокрапки, але ніхто не заважає використовувати тут і що-небудь інше - все залежить від конкретного завдання.
Тепер треба пройтися по отриманому списку в циклі і виконати там необхідні для підрахунку кількості файлів дії. Загальна схема скрипта буде такою:

Mypath = $ (echo $ PATH | sed "s /: / / g") for directory in $ mypath do done
Тепер напишемо повний текст скрипта, скориставшись командою ls для отримання відомостей про кількість файлів у кожній з директорій:

#! / Bin / bash mypath = $ (echo $ PATH | sed "s /: / / g") count = 0 for directory in $ mypath do check = $ (ls $ directory) for item in $ check do count = $ [$ count + 1] done echo "$ directory - $ count" count = 0 done
При запуску скрипта може виявитися, що деяких директорій з PATH не існує, однак, це не завадить йому порахувати файли в існуючих директоріях.


підрахунок файлів

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

▍Проверка адрес електронної пошти

Існують веб-сайти з величезними колекціями регулярних виразів, які дозволяють перевіряти адреси електронної пошти, номери телефонів, і так далі. Однак, одна справа - взяти готове, і зовсім інша - створити щось самому. Тому напишемо регулярний вираз для перевірки адрес електронної пошти. Почнемо з аналізу вихідних даних. Ось, наприклад, якийсь адреса:

[Email protected]
Ім'я користувача, username, може складатися з алфавітно-цифрових і деяких інших символів. А саме, це крапка, тире, символ підкреслення, знак «плюс». За ім'ям користувача слід знак @.

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

^(+)@
Це регулярний вираз можна прочитати так: «На початку рядка повинен бути як мінімум один символ з тих, які є в групі, заданої в квадратних дужках, а після цього повинен йти знак @».

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

(+)
Ім'я домену верхнього рівня підпорядковується особливими правилами. Тут можуть бути лише алфавітні символи, яких повинно бути не менше двох (наприклад, такі домени зазвичай містять код країни), і не більше п'яти. Все це означає, що шаблон для перевірки останньої частини адреси буде таким:

\.({2,5})$
Прочитати його можна так: «Спочатку повинна бути точка, потім - від 2 до 5 алфавітних символів, а після цього рядок закінчується».

Підготувавши шаблони для окремих частин регулярного виразу, зберемо їх разом:

^(+)@(+)\.({2,5})$
Тепер залишилося лише протестувати то, що вийшло:

$ Echo " [Email protected]"| Awk" /^(+)@(+)\.((2,5))$/(print $ 0) "$ echo" [Email protected]"| Awk" /^(+)@(+)\.((2,5))$/(print $ 0) "


Перевірка адреси електронної пошти за допомогою регулярних виразів

Те, що переданий awk текст виводиться на екран, означає, що система розпізнала в ньому адресу електронної пошти.

підсумки

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

У цій серії матеріалів ми зазвичай показували дуже прості приклади bash-скриптів, які складалися буквально з кількох рядків. Наступного разу розглянемо дещо масштабніше.

Шановні читачі! А ви користуєтеся регулярними виразами при обробці текстів в сценаріях командного рядка?

Сподобалася стаття? Поділіться з друзями!