Разное

Shell регулярные выражения: регулярные выражения / Блог компании RUVDS.com / Хабр

Содержание

регулярные выражения / Блог компании RUVDS.com / Хабр

Bash-скрипты: начало
Bash-скрипты, часть 2: циклы
Bash-скрипты, часть 3: параметры и ключи командной строки
Bash-скрипты, часть 4: ввод и вывод
Bash-скрипты, часть 5: сигналы, фоновые задачи, управление сценариями
Bash-скрипты, часть 6: функции и разработка библиотек
Bash-скрипты, часть 7: sed и обработка текстов
Bash-скрипты, часть 8: язык обработки данных awk
Bash-скрипты, часть 9: регулярные выражения
Bash-скрипты, часть 10: практические примеры
Bash-скрипты, часть 11: expect и автоматизация интерактивных утилит

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

Этот материал задуман как введение в регулярные выражения, рассчитанное на тех, кто может совершенно не знать о том, что это такое. Поэтому начнём с самого начала.

Что такое регулярные выражения

У многих, когда они впервые видят регулярные выражения, сразу же возникает мысль, что перед ними бессмысленное нагромождение символов. Но это, конечно, далеко не так. Взгляните, например, на это регулярное выражение

^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$

На наш взгляд даже абсолютный новичок сходу поймёт, как оно устроено и зачем нужно 🙂 Если же вам не вполне понятно — просто читайте дальше и всё встанет на свои места.
Регулярное выражение — это шаблон, пользуясь которым программы вроде 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 '/[oi]th/{print $0}' myfile

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

Тут мы ищем последовательность символов «th», перед которой есть символ «o» или символ «i».

Классы оказываются очень кстати, если выполняется поиск слов, которые могут начинаться как с прописной, так и со строчной буквы:

$ echo "this is a test" | awk '/[Tt]his is a test/{print $0}'
$ echo "This is a test" | awk '/[Tt]his is a test/{print $0}'

Поиск слов, которые могут начинаться со строчной или прописной буквы

Классы символов не ограничены буквами. Тут можно использовать и другие символы. Нельзя заранее сказать, в какой ситуации понадобятся классы — всё зависит от решаемой задачи.

Отрицание классов символов

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

$ awk '/[^oi]th/{print $0}' myfile

Поиск символов, не входящих в класс

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

Диапазоны символов

В символьных классах можно описывать диапазоны символов, используя тире:

$ awk '/[e-p]st/{print $0}' myfile

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

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

Диапазоны можно создавать и из чисел:

$ echo "123" | awk '/[0-9][0-9][0-9]/'
$ echo "12a" | awk '/[0-9][0-9][0-9]/'

Регулярное выражение для поиска трёх любых чисел

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

$ awk '/[a-fm-z]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[ae]*t/{print $0}'
$ echo "sat" | awk '/s[ae]*t/{print $0}'
$ echo "set" | awk '/s[ae]*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[ae]?st/{print $0}'
$ echo "test" | awk '/t[ae]?st/{print $0}'
$ echo "tast" | awk '/t[ae]?st/{print $0}'
$ echo "taest" | awk '/t[ae]?st/{print $0}'
$ echo "teest" | awk '/t[ae]?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[ae]+st/{print $0}'
$ echo "test" | awk '/t[ae]+st/{print $0}'
$ echo "teast" | awk '/t[ae]+st/{print $0}'
$ echo "teeast" | awk '/t[ae]+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[ae]{1,2}st/{print $0}'
$ echo "test" | awk  '/t[ae]{1,2}st/{print $0}'
$ echo "teest" | awk  '/t[ae]{1,2}st/{print $0}'
$ echo "teeast" | awk  '/t[ae]{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, может состоять из алфавитно-цифровых и некоторых других символов. А именно, это точка, тире, символ подчёркивания, знак «плюс». За именем пользователя следует знак @.

Вооружившись этими знаниями, начнём сборку регулярного выражения с его левой части, которая служит для проверки имени пользователя. Вот что у нас получилось:

^([a-zA-Z0-9_\-\.\+]+)@

Это регулярное выражение можно прочитать так: «В начале строки должен быть как минимум один символ из тех, которые имеются в группе, заданной в квадратных скобках, а после этого должен идти знак @».

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

([a-zA-Z0-9_\-\.]+)

Имя домена верхнего уровня подчиняется особым правилам. Тут могут быть лишь алфавитные символы, которых должно быть не меньше двух (например, такие домены обычно содержат код страны), и не больше пяти. Всё это значит, что шаблон для проверки последней части адреса будет таким:

\.([a-zA-Z]{2,5})$

Прочесть его можно так: «Сначала должна быть точка, потом — от 2 до 5 алфавитных символов, а после этого строка заканчивается».

Подготовив шаблоны для отдельных частей регулярного выражения, соберём их вместе:

^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$

Теперь осталось лишь протестировать то, что получилось:

$ echo "[email protected]" | awk '/^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/{print $0}'
$ echo "[email protected]" | awk '/^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/{print $0}'

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

То, что переданный awk текст выводится на экран, означает, что система распознала в нём адрес электронной почты.

Итоги

Если регулярное выражение для проверки адресов электронной почты, которое встретилось вам в самом начале статьи, казалось тогда совершенно непонятным, надеемся, сейчас оно уже не выглядит бессмысленным набором символов. Если это действительно так — значит данный материал выполнил своё предназначение. На самом деле, регулярные выражения — это тема, которой можно заниматься всю жизнь, но даже то немногое, что мы разобрали, уже способно помочь вам в написании скриптов, которые довольно продвинуто обрабатывают тексты.

В этой серии материалов мы обычно показывали очень простые примеры bash-скриптов, которые состояли буквально из нескольких строк. В следующий раз рассмотрим кое-что более масштабное.

Уважаемые читатели! А вы пользуетесь регулярными выражениями при обработке текстов в сценариях командной строки?

Регулярные выражения Linux | Losst

Регулярные выражения — это очень мощный инструмент для поиска текста по шаблону, обработки и изменения строк, который можно применять для решения множества задач. Вот основные из них:

  • Проверка ввода текста;
  • Поиск и замена текста в файле;
  • Пакетное переименование файлов;
  • Взаимодействие  с сервисами, таким как Apache;
  • Проверка строки на соответствие шаблону.

Это далеко не полный список, регулярные выражения позволяют делать намного больше. Но для новых пользователей они могут показаться слишком сложными, поскольку для их формирования используется специальный язык. Но учитывая предоставляемые возможности, регулярные выражения Linux должен знать и уметь использовать каждый системный администратор.

В этой статье мы рассмотрим регулярные выражения bash для начинающих, чтобы вы смогли разобраться со всеми возможностями этого инструмента.

Содержание статьи:

Регулярные выражения Linux

В регулярных выражениях могут использоваться два типа символов:

  • обычные буквы;
  • метасимволы.

Обычные символы — это буквы, цифры и знаки препинания, из которых состоят любые строки. Все тексты состоят из букв и вы можете использовать их в регулярных выражениях для поиска нужной позиции в тексте.

Метасимволы — это кое-что другое, именно они дают силу регулярным выражениям. С помощью метасимволов вы можете сделать намного больше чем поиск одного символа. Вы можете искать комбинации символов, использовать динамическое их количество и выбирать диапазоны. Все спецсимволы можно разделить на два типа, это символы замены, которые заменяют собой обычные символы, или операторы, которые указывают сколько раз может повторяться символ. Синтаксис регулярного выражения будет выглядеть таким образом:

обычный_символ спецсимвол_оператор

спецсимвол_замены спецсимвол_оператор

Если оператор не указать, то будет считаться, что символ обязательно должен встретится в строке один раз. Таких конструкций может быть много. Вот основные метасимволы, которые используют регулярные выражения bash:

  • \ — с обратной косой черты начинаются буквенные спецсимволы, а также он используется если нужно использовать спецсимвол в виде какого-либо знака препинания;
  • ^ — указывает на начало строки;
  • $ — указывает на конец строки;
  • * — указывает, что предыдущий символ может повторяться 0 или больше раз;
  • + — указывает, что предыдущий символ должен повторится больше один или больше раз;
  • ? — предыдущий символ может встречаться ноль или один раз;
  • {n} — указывает сколько раз (n) нужно повторить предыдущий символ;
  • {N,n} — предыдущий символ может повторяться от N до n раз;
  • . — любой символ кроме перевода строки;
  • [az] — любой символ, указанный в скобках;
  • х|у — символ x или символ y;
  • [^az] — любой символ, кроме тех, что указаны в скобках;
  • [a-z] — любой символ из указанного диапазона;
  • [^a-z] — любой символ, которого нет в диапазоне;
  • \b — обозначает границу слова с пробелом;
  • \B — обозначает что символ должен быть внутри слова, например, ux совпадет с uxb или tuxedo, но не совпадет с Linux;
  • \d — означает, что символ — цифра;
  • \D — нецифровой символ;
  • \n — символ перевода строки;
  • \s — один из символов пробела, пробел, табуляция и так далее;
  • \S — любой символ кроме пробела;
  • \t — символ табуляции;
  • \v — символ вертикальной табуляции;
  • \w — любой буквенный символ, включая подчеркивание;
  • \W — любой буквенный символ, кроме подчеркивания;
  • \uXXX — символ Unicdoe.

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

Например, вы хотите найти в тексте строку 1+ 2=3. Если вы используете эту строку в качестве регулярного выражения, то ничего не найдете, потому что система интерпретирует плюс как спецсимвол, который сообщает, что предыдущая единица должна повториться один или больше раз. Поэтому его нужно экранировать: 1 \+ 2 = 3. Без экранирования наше регулярное выражение соответствовало бы только строке 11=3 или 111=3 и так далее. Перед равно черту ставить не нужно, потому что это не спецсимвол.

Примеры использования регулярных выражений

Теперь, когда мы рассмотрели основы и вы знаете как все работает, осталось закрепить полученные знания про регулярные выражения linux grep на практике. Два очень полезные спецсимвола — это ^ и $, которые обозначают начало и конец строки. Например, мы хотим получить всех пользователей, зарегистрированных в нашей системе, имя которых начинается на s. Тогда можно применить регулярное выражение «^s». Вы можете использовать команду egrep:

egrep "^s" /etc/passwd

Если мы хотим отбирать строки по последнему символу в строке, что для этого можно использовать $. Например, выберем всех системных пользователей, без оболочки, записи о таких пользователях заканчиваются на false:

egrep "false$" /etc/passwd

 

Чтобы вывести имена пользователей, которые начинаются на s или d используйте такое выражение:

egrep "^[sd]" /etc/passwd

Такой же результат можно получить, использовав символ «|». Первый вариант более пригоден для диапазонов, а второй чаще применяется для обычных или/или:

egrep "^[s|d]" /etc/passwd

Теперь давайте выберем всех пользователей, длина имени которых составляет не три символа. Имя пользователя завершается двоеточием. Мы можем сказать, что оно может содержать любой буквенный символ, который должен быть повторен три раза, перед двоеточием:

egrep "^\w{3}:" /etc/passwd

Выводы

В этой статье мы рассмотрели регулярные выражения Linux, но это были только самые основы. Если копнуть чуть глубже, вы найдете что с помощью этого инструмента можно делать намного больше интересных вещей. Время, потраченное на освоение регулярных выражений, однозначно будет стоить того.

На завершение лекция от Яндекса про регулярные выражения:

Источник: www.linux.com

Регулярные выражения в командной оболочке Bash

Регулярные выражения (RegEx или RegExp) — это набор символов, которые определяют шаблон поиска. Их можно использовать для выполнения операций «Поиск» или «Поиск и замена», а также для проверки условий, таких как политика паролей, ввод номера телефона и т.д.

Облачные серверыIntel Xeon Gold 6254 3.1 GHz CPU, SLA 99,9%от249 руб/месяцПопробовать

Приведем пример регулярного выражения:

/t[aeiou]l/

Это регулярное выражение будет искать слово, начинающееся с буквы ‘t’, содержащее любую из букв ‘a e i o u’ в середине и оканчивающееся буквой ‘l’. Это может быть ‘tel’, ‘tal’ или ’til’. Совпадение может быть отдельным словом или частью другого слова, например ’tilt’, ‘brutal’ или ‘telephone’.

А теперь приступим к рассмотрению основных регулярных выражений на примере командной оболочки Bash.

Основы регулярных выражений

В общем виде синтаксис команды ‘grep’ выглядит следующим образом:

$ grep поисковый_запрос_regex расположение_файла

Изучим некоторые специальные символы, известные как метасимволы. Они помогают создавать более сложные поисковые выражения:

. будет соответствовать любому символу;
[ ] будет соответствовать диапазону символов;
[^ ] будет соответствовать всем символам, кроме указанных в фигурных скобках;
* будет соответствовать любому количеству символов, предшествующих звездочке, в том числе нулю;
+ будет соответствовать одному или нескольким из стоящих перед ним выражений;
? будет соответствовать нулю или одному из стоящих перед ним выражений;
{n} будет соответствовать ‘n’ повторениям предшествующих выражений;
{n,} будет соответствовать не менее ‘n’ повторениям предшествующих выражений;
{n m} будет соответствовать не менее ‘n’ и не более ‘m’ повторениям предшествующих выражений;
{,m} будет соответствовать не более или равному ‘m’ повторениям предшествующих выражений;
является escape-символом (символом экранирования), используемым, когда нужно включить один из метасимволов.

Приведем примеры

. (точка)

Используется для соответствия любому символу, который встречается в поисковом запросе. Например, можем использовать точку как:

$ grep "d.g" file1

Это регулярное выражение означает, что мы ищем слово, которое начинается с ‘d’, оканчивается на ‘g’ и может содержать один любой символ в середине файла с именем ‘file1’. Точно так же мы можем использовать символ точки любое количество раз для нашего шаблона поиска, например:

T......h

Этот поисковый термин будет искать слово, которое начинается с ‘T’, оканчивается на ‘h’ и может содержать любые шесть символов в середине.

[ ]

Квадратные скобки используются для определения диапазона символов. Например, когда нужно искать один из перечисленных символов, а не любой символ, как в случае с точкой:

$ grep "N[oen]n" file2

Здесь мы ищем слово, которое начинается с ‘N’, оканчивается на ‘n’ и может иметь только ‘o’, ‘e’ или ‘n’ в середине. В квадратных скобках можно использовать любое количество символов. Мы также можем определить диапазоны, такие как ‘a-e’ или ‘1-18’, как список совпадающих символов в квадратных скобках.

[^ ]

Это похоже на оператор отрицания для регулярных выражений. Использование [^ ] означает, что поиск будет включать в себя все символы, кроме тех, которые указаны в квадратных скобках. Например:

$ grep "St[^1-9]d" file3

Это означает, что у нас могут быть все слова, которые начинаются с ‘St’, оканчиваются буквой ‘d’ и не содержат цифр от 1 до 9.

До сих пор мы использовали примеры регулярных выражений, которые ищут только один символ. Но что делать в иных случаях? Допустим, если требуется найти все слова, которые начинаются или оканчиваются символом или могут содержать любое количество символов в середине. С этой задачей справляются так называемые метасимволы-квантификаторы, определяющие сколько раз может встречаться предшествующее выражение: + * & ?

{n}, {n m}, {n, } или { ,m} также являются примерами других квантификаторов, которые мы можем использовать в терминах регулярных выражений.

* (звездочка)

На следующем примере показано любое количество вхождений буквы ‘k’, включая их отсутствие:

$ grep "lak*" file4

Это означает, что у нас может быть совпадение с ‘lake’ или ‘la’ или ‘lakkkkk’.

+

Следующий шаблон требует, чтобы хотя бы одно вхождение буквы ‘k’ в строке совпадало:

$ grep "lak+" file5

Здесь буква ‘k’ должна появляться хотя бы один раз, поэтому наши результаты могут быть ‘lake’ или ‘lakkkkk’, но не ‘la’.

?

В следующем шаблоне результатом будет строка bb или bab:

$ grep "ba?b" file6

С заданным квантификатором ‘?’ мы можем иметь одно вхождение символа или ни одного.

Важное примечание! Предположим, у нас есть регулярное выражение:

$ grep "S.*l" file7

И мы получаем результаты ‘Small’, ‘Silly’, и ещё ‘Susan is a little to play ball’. Но почему мы получили ‘Susan is a little to play ball’, ведь мы искали только слова, а не полное предложение?

Все дело в том, что это предложение удовлетворяет нашим критериям поиска: оно начинается с буквы ‘S’, имеет любое количество символов в середине и заканчивается буквой ‘l’. Итак, что мы можем сделать, чтобы исправить наше регулярное выражение, чтобы в качестве выходных данных мы получали только слова вместо целых предложений.

Для этого в регулярное выражение нужно добавить квантификатор ‘?’:

$ grep "S.*?l" file7

или символ экранирования

Символ » используется, когда необходимо включить символ, который является метасимволом или имеет специальное значение для регулярного выражения. Например, требуется найти все слова, заканчивающиеся точкой. Для этого можем использовать выражение:

$ grep "S.*?." file8

Оно будет искать и сопоставлять все слова, которые заканчиваются точкой.

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

Регулярные выражения, основы для работы в Linux

Доброго времени, гости!

В сегодняшней статье хочу коснуться такой огромной темы как Регулярные выражения. Думаю всем известно, что тема регексов (так регулярные выражения называются на сленге) — необъятна в объеме одного поста. Посему постараюсь кратко, но как можно понятней собрать в кучу свои мысли и донести их до Вас в своем блоге.

Начну с того, что существует несколько разновидностей регулярных выражений:

1. Традиционные регулярные выражения (они же основные, базовые и basic regular expressions (BRE))

  • синтаксис данных выражений определен, как устаревший, но тем не менее до сих пор широко распространен и  используется многими утилитами UNIX
  • Основные регулярные выражения включают в себя следующие метасимволы (об их значениях ниже):
    • .
    • [ ]
    • [^ ]
    • ^
    • $
    • *
    • \{ \} — первоначальный вариант для { } (в расширенных)
    • \( \) — первоначальный вариант для ( )(в расширенных)
    • \n, где n — номер от 1 до 9
  • Особенности использования данных метасимволов:
    • Звёздочка должна следовать после выражения, соответствующего единичному символу. Пример: [xyz]*.
    • Выражение \(блок\)* следует считать неправильным. В некоторых случаях оно соответствует нулю или более повторений строки блок. В других оно соответствует строке блок*.
    • Внутри символьного класса специальные значения символов, в основном, игнорируются. Особые случаи:
    • Чтобы добавить символ ^ в набор, его следует поместить туда не первым.
    • Чтобы добавить символ -в набор, его следует поместить туда первым или последним. Например:
      • шаблон DNS-имени, куда могут входить буквы, цифры, минус и точка-разделитель: [-0-9a-zA-Z.];
      • любой символ, кроме минуса и цифры: [^-0-9].
    • Чтобы добавить символ [ или ]в набор, его следует поместить туда первым. Например:
      • [][ab] соответствует ], [, a или b.

2. Расширенные регулярные выражения (они же extended regular expressions (ERE))

  • Синтаксис данных выражений аналогичен синтаксису основных выражений, за исключением:
    • Отменено использование обратной косой черты для метасимволов { } и ( ).
    • Обратная косая черта перед метасимволом отменяет его специальное значение.
    • Отвергнута теоретически нерегулярная конструкция \n.
    • Добавлены метасимволы +, ?, |.

3. Регулярные выражения, совместимые с Perl (они же Perl-compatible regular expressions (PCRE))

  • имеют более богатый и в то же время предсказуемый синтаксис, чем даже POSIX ERE, поэтому часто используется приложениями.

Далее немного поговорим о синтаксисе регулярных выражений.

Регулярные выражения состоят из шаблонов, вернее сказать задают шаблон поиска. Шаблон состоит из правил поиска, которые составляются из символов и метасимволов.

Правила поиска определяются следующими операциями:

Перечисление |

Вертикальная черта (|) разделяет допустимые варианты, можно сказать — логическое ИЛИ. Например, «gray|grey» соответствует gray или grey.

Группировка или объединение ( )

Круглые скобки используются для определения области действия и приоритета операторов. Например, «gray|grey» и «gr(a|e)y» являются разными образцами, но они оба описывают множество, содержащее gray и grey.

Квантификация {} ? * +

Квантификатор после символа или группы определяет, сколько раз предшествующее выражение может встречаться.

{m,n}

общее выражение, повторений может быть от m до n включительно.

{m,}

общее выражение, m и более повторений.

{,n}

общее выражение, не более n повторений.

{n}

ровно n повторений.

?

Знак вопроса означает 0 или 1 раз, то же самое, что и {0,1}. Например, «colou?r» соответствует и color, и colour.

*

Звёздочка означает 0, 1 или любое число раз ({0,}). Например, «go*gle» соответствует ggle, gogle, google и др.

+

Плюс означает хотя бы 1 раз ({1,}). Например, «go+gle» соответствует gogle, google и т. д. (но не ggle).

Конкретный синтаксис данных регулярных выражений зависит от реализации. (то есть в базовых регулярных выражениях символы { и } — экранируются обратным слешем)

Метасимволы, говоря простым языком — это символы, которые не соответствуют своему реальному значению, то есть символ . (точка) — это не точка, а любой один символ, и т.п. прошу ознакомиться с метасимволами и их значениями:

. соответствует одному любому символу
[что-то] Соответствует любому единичномусимволу из числа заключённых в скобки. При этом:Символ «-» интерпретируется буквально только в том случае, если он расположен непосредственно после открывающей или перед закрывающей скобкой: [abc-] или [-abc]. В противном случае, он обозначает интервал символов.Например, [abc] соответствует «a», «b» или «c». [a-z] соответствует буквам нижнего регистра латинского алфавита. Эти обозначения могут и сочетаться: [abcq-z] соответствует a, b, c, q, r, s, t, u, v, w, x, y, z.Чтобы установить соответствие символам «[» или «]», достаточно, чтобы закрывающая скобка была первым символом после открывающей: [][ab] соответствует «]», «[», «a» или «b».Если значение в квадратных скобах предварено символом ^, то значение выражения соответствует единичному символу из числа тех, которых нет в скобках. Например, [^abc] соответствует любому символу, кроме «a», «b» или «c». [^a-z] соответствует любому символу, кроме символов нижнего регистра в латинском алфавите.
^ Соответствует началу текста (или началу любой строки, если режим построчный).
$ Соответствует концу текста (или концу любой строки, если режим построчный).
\(\) или ( ) Объявляет «отмеченное подвыражение» (сгруппированное выражение), которое может быть использовано позже (см. следующий элемент: \n). «Отмеченное подвыражение» также является «блоком». В отличие от других операторов, этот (в традиционном синтаксисе) требует бэкслеша, в расширенном и Perl символ \ — не нужен.
\n Где n — это цифра от 1 до 9; соответствует n-му отмеченному подвыражению (например (abcd)\0, то есть символы abcd отмечены нулем). Эта конструкция теоретически нерегулярна, она не была принята в расширенном синтаксисе регулярных выражений.
*
  • Звёздочка после выражения, соответствующего единичному символу, соответствует нулю или более копий этого (предшествующего) выражения. Например, «[xyz]*» соответствует пустой строке, «x», «y», «zx», «zyx», и т. д.
  • \n*, где n — это цифра от 1 до 9, соответствует нулю или более вхождений для соответствия n-го отмеченного подвыражения. Например, «\(a.\)c\1*» соответствует «abcab» и «abcaba», но не «abcac».

!!! Выражение, заключённое в «\(» и «\)» и сопровождаемое «*», следует считать неправильным. В некоторых случаях, оно соответствует нулю или более вхождений строки, которая была заключена в скобки. В других, оно соответствует выражению, заключённому в скобки, учитывая символ «*».

\{x,y\} Соответствует последнему (предстоящему) блоку, встречающемуся не менее x и не более y раз. Например, «a\{3,5\}» соответствует «aaa», «aaaa» или «aaaaa». В отличие от других операторов, этот (в традиционном синтаксисе) требует бэкслеша.
.* Обозначение любого количества любых символов между двумя частями регулярного выражения.

Метасимволы нам помогают использовать различные соответствия. Но как же представить метасимвол обычным символом, то есть символ [ (квадратная скобка) значением квадратной скобки? Просто:

  • необходимо предварить (экранировать) метасимвол (. * + \ ? [ ] { } ) обратным слешем. Например \. или \[

Для упрощения задания некоторых наборов символов, их объединили в т.н.классы и категории символов. POSIX стандартизовал объявление некоторых классов и категорий символов, как показано в следующей таблице:

POSIX класс аналогично обозначение
[:upper:] [A-Z] символы верхнего регистра
[:lower:] [a-z] символы нижнего регистра
[:alpha:] [A-Za-z] символы верхнего и нижнего регистра
[:alnum:] [A-Za-z0-9] цифры, символы верхнего и нижнего регистра
[:digit:] [0-9] цифры
[:xdigit:] [0-9A-Fa-f] шестнадцатеричные цифры
[:punct:] [.,!?:…] знаки пунктуации
[:blank:] [ \t] пробел и TAB
[:space:] [ \t\n\r\f\v] символы пропуска
[:cntrl:] символы управления
[:graph:] [^ \t\n\r\f\v] символы печати
[:print:] [^\t\n\r\f\v] символы печати и символы пропуска

В regex есть такое понятие как:

Жадность regex

Постараюсь описать как можно понятней. Допустим, мы хотим найти все HTML теги в каком-то тексте. Локализовав задачу, мы хотим найти значения заключенные между < и >, вместе с этими самыми скобками. Но мы знаем, что теги имеют разную длину и самих тегов, как минимум штук 50. Перечислять их все , заключив в метасимволы [] — задача слишком трудоемкая. Но мы знаем, что у нас есть выражение .* (точка звездочка), характеризующее любое число любых символов в строке. С помощью данного выражения мы попытаемся найти в тексте (<p>Итак, <strong>Как создать RAID уровня 10/50 на контроллере LSI MegaRAID (актуально и для: Intel SRCU42x, Intel SRCS16):</strong><span></span></p>) все значения между < и >. В результате, этому выражению будет соответствовать ВСЯ строка. почему, потому что регекс — ЖАДЕН и старается захватить ЛЮБОЕ ВСЕ количество символов между < и >, соответственно вся строка, начиная <p>Итак,… и заканчивая …</span></p> будет принадлежать данному правилу!

Надеюсь, на примере понятно что такое жадность. Чтобы избавиться от данной жадности, можно пойти по следующему пути:

  • учесть символы, не соответствующие желаемому образцу (например: <[^>]*> для вышеописанного случая)
  • избавить от жадности, добавив определении квантификатора, как нежадного:
    • *? — «не жадный» («ленивый») эквивалент *
    • +? — «не жадный» («ленивый») эквивалент +
    • {n,}? — «не жадный» («ленивый») эквивалент {n,}
    • .*? — «не жадный» («ленивый») эквивалент .*

Все вышенаписанное хочу дополнить синтаксисом расширенных регулярных выражений:

Регулярные выражения в POSIX аналогичны традиционному Unix-синтаксису, но с добавлением некоторых метасимволов:

+

Плюс указывает на то, что предыдущий символ или группа может повторяться один или несколько раз. В отличие от звёздочки, хотя бы одно повторение обязательно.

?

Знак вопроса делает предыдущий символ или группу необязательной. Другими словами, в соответствующей строке она может отсутствовать, либо присутствовать ровно один раз.

|

Вертикальная черта разделяет альтернативные варианты регулярных выражений. Один символ задаёт две альтернативы, но их может быть и больше, достаточно использовать больше вертикальных чёрточек. Необходимо помнить, что этот оператор использует максимально возможную часть выражения. По этой причине, оператор альтернативы чаще всего используется внутри скобок.

Также было отменено использование обратной косой черты: \{…\} становится {…} и \(…\) становится (…).

В завершение поста, приведу некоторые примеры использования regex:

[[email protected] k-max.name]$ cat text1
1 apple
2 pear
3 banana
[[email protected] k-max.name]$ grep p text1
1 apple
2 pear
[[email protected] k-max.name]$ grep pea text1
2 pear
[[email protected] k-max.name]$ grep "p*" text1
1 apple
2 pear
3 banana
[[email protected] k-max.name]$ grep "pp*" text1
1 apple
2 pear
[[email protected] k-max.name]$ grep "x" text1
[[email protected] k-max.name]$ grep "x*" text1
1 apple
2 pear
3 banana
[[email protected] k-max.name]$ cat text1 | grep "l\|n"
1 apple
3 banana
[[email protected] k-max.name]$ echo -e "find an\n* here" | grep "\*"
* here
[[email protected] k-max.name]$ grep "pp\+" text1 # строки, с содержанием одной р и 1 и более р
1 apple
[[email protected] k-max.name]$ grep "pl\?e" text1
1 apple
2 pear
[[email protected] k-max.name]$ grep "pl\?e" text1 # pe с возможным символом l
1 apple
2 pear
[[email protected] k-max.name]$ grep "p.*r" text1 # p, в строках где есть r
2 pear
[[email protected] k-max.name]$ grep "a.." text1 # строки с a, за которой следует как минимум 2 символа
1 apple
3 banana
[[email protected] k-max.name]$ grep "\(an\)\+" text1 # Поиск более повторения an
3 banana
[[email protected] k-max.name]$ grep "an\(an\)\+" text1 # поиск 2х повторений an
3 banana
[[email protected] k-max.name]$ grep "[3p]" text1 # поиск строк, где есть 3 или p
1 apple
2 pear
3 banana
[[email protected] k-max.name]$ echo -e "find an\n* here\nsomewhere." | grep "[.*]"
* here
somewhere.
[[email protected] k-max.name]$ # Ищет символы от 3 до 7
[[email protected] k-max.name]$ echo -e "123\n456\n789\n0" | grep "[3-7]"
123
456
789
[[email protected] k-max.name]$ # Ищем цифру, за которой до конца строки нет букв n и r
[[email protected] k-max.name]$ grep "[[:digit:]][^nr]*$" text1
1 apple
[[email protected] k-max.name]$ sed -e '/\(a.*a\)\|\(p.*p\)/s/a/A/g' text1 # замена а на А во всех строках, где после а идет а или после р идет р
1 Apple
2 pear
3 bAnAnA
[[email protected] k-max.name]$ sed -e '/^[^lmnXYZ]*$/s/ear/each/g' text1 # замена ear на each в строках не начинающихся на lmnXYZ
1 apple
2 peach
3 banana
[[email protected] k-max.name]$ echo "First. A phrase. This is a sentence." |\ # замена последнего слова в предложении на LAST WORLD.
&amp;amp;gt; sed -e 's/ [^ ]*\./ LAST WORD./g'
First. A LAST WORD. This is a LAST WORD.

С Уважением, Mc.Sim!


Другие материалы в категории основы Linux


Теги: bash, Linux, regex, sed, UNIX, команды, основы

BASH: регулярные выражения: =~ и BASH_REMATCH

В BASH версии 3.0 и выше имеется специальный оператор для работы с регулярными выражениями =~.

 

Для примера возьмём такой скрипт:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
regex=".*.MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        echo -e "Found file: $file"
    fi
done

Результат:

$ ./reg.sh
Found file: /var/lib/mysql/rtfm_db1/db1_commentmeta.MYI
Found file: /var/lib/mysql/rtfm_db1/db1_comments.MYI
Found file: /var/lib/mysql/rtfm_db1/db1_links.MYI
...
Found file: /var/lib/mysql/rtfm_db1/db1_usermeta.MYI
Found file: /var/lib/mysql/rtfm_db1/db1_users.MYI

Результат проверкирегулярного выржения хранится в переменной BASH_REMATCH. Т.е. скрипт можно переписать так:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
regex=".*.MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        echo -e "Found file: $BASH_REMATCH"
    fi
done

И даже больше — массивом:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
regex=".*.MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        echo -e "Found file: ${BASH_REMATCH[@]}"
    fi
done

В данном случае — массив будет хранить только один элемент:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
regex=".*.MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        # выводим кол-во элемента массива
        echo -e "Found file: ${#BASH_REMATCH[@]}"
    fi
done
$ ./reg.sh
Found file: 1
Found file: 1
Found file: 1

Смысл массива становится более понятен, если мы используем скобки в регулярном выражении для получения (или «захвата») каких-то данных, например:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
# добавляем захват значения
regex="db1_(.*).MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        # выводим количество элементов массива
        echo -e "Number of BASH_REMATCH array elements: ${#BASH_REMATCH[@]}"
        # вся строка, которая попала под фильтр регулярного выражения - первый (индекс 0) элемент массива
        echo -e "Full capture string: ${BASH_REMATCH[0]}"
        # второй элемент массива (индекс 1) - захваченное () в регулярном выражении значение
        echo -e "Captured string element: ${BASH_REMATCH[1]}"
    fi
done

Результат:

$ ./reg.sh
Number of BASH_REMATCH array elements: 2
Full capture string: db1_commentmeta.MYI
Captured string element: commentmeta
...
Number of BASH_REMATCH array elements: 2
Full capture string: db1_users.MYI
Captured string element: users

 

Регулярные выражения за 15 минут

  1. Доступные статьи

  2. IT-шное

  3. Регулярные выражения за 15 минут

Регулярные выражения (regular expressions) — это текстовый шаблон, который соответствует какому-то тексту. И всё? Да, это всё, для чего они нужны.

Что можно делать с помощью регулярных выражений:

  • Проверять то, что вводит пользователь, чтобы быть уверенным в правильности данных (например, правильно ли пользователь ввёл email или ip-адрес).
  • Разбирать большой текст на меленькие кусочки (например, выбирать данные из большого лога).
  • Делать замены по шаблону (например, убирать непечатаемые символы из XML).
  • Показывать невероятную крутость тем, кто не знает регулярных выражений.

Большинство современных языков программирования и текстовых редакторов (по моему личному мнению) поддерживают регулярные выражения. Поддержим их и мы.

/Быть или не быть/ugi ¶

Синтаксис регулярных выражений прост и логичен. Он разделяется на символ-разделитель (он идёт в начале и конце выражения, обычно это /), шаблон поиска и необязательные модификаторы.

Формальный синтаксис такой:

[разделитель][шаблон][разделитель][модификаторы]

Разделителем может быть любой символ, но обычно это / или ~. Важно лишь то, чтобы шаблон начинался и заканчивался одним и тем же разделителем. В самом конце регулярных выражений идут модификаторы, которые нужны, чтобы менять логику работы шаблонов (например делать регистронезависимый поиск).

Давайте разберём выражение /Быть или не быть/ugi:

/                - начальный символ-разделитель
Быть или не быть - шаблон поиска
/                - конечный символ-разделитель
ugi              - модификаторы (UTF-8, global, case insensitive)

Данное регулярное выражение будет искать текст Быть или не быть не зависимо от регистра по всему тексту неограниченное количество раз. Модификатор u нужен для того, чтобы явно указать, что текст у нас в юникоде, то есть содержит символы, отличные от латиницы. Модификатор i включает регистронезависимый поиск. Модификатор g указывает поисковику идти до победного конца, иначе он остановится после первого удачного совпадения.

«Петя любит Дашу».replace(/Дашу|Машу|Сашу/, «Катю») ¶

Не трудно догадаться, что результатом работы js-выражения выше будет текст "Петя любит Катю". Даже, если Петя неровно дышит к Маше или Саше, то результат всё равно не изменится.

Рассмотрим базовые спец. символы, которые можно использовать в шаблонах:

Символ Описание Пример использования Результат
\ Символ экранирования или начала мета-символа /путь\/к\/папке/ Надёт текст путь/к/папке
^ Признак начала строки /^Дом/ Найдёт все строки, которые начинаются на Дом
$ Признак конца строки /родной$/ Найдёт все строки, которые заканчиваются на родной
. Точка означает любой символ, кроме перевода строки /Петя ..бит Машу/ Найдёт как Петя любит Машу, так и Петя губит Машу
| Означает ИЛИ /Вася|Петя/ Найдёт как Васю, так и Петю
? Означает НОЛЬ или ОДИН раз /Вжу?х/ Найдёт Вжх и Вжух
* Означает НОЛЬ или МНОГО раз /Вжу*х/ Найдёт Вжх, Вжух, Вжуух, Вжууух и т.д.
+ Означает ОДИН или МНОГО раз /Вжу+х/ Найдёт Вжух, Вжуух, Вжууух и т.д.

Помимо базовых спец. символов есть мета-символы (или мета-последовательности), которые заменяют группы символов:

Символ Описание Пример использования Результат
\w Буква, цифра или _ (подчёркивание) /^\w+$/ Соответствует целому слову без пробелов, например _Вася333_
\W НЕ буква, цифра или _ (подчёркивание) /\W\w+\W/ Найдёт полное слово, которое обрамлено любыми символами, например @Петя@
\d Любая цифра /^\d+$/ Соответствует целому числу без знака, например 123
\D Любой символ НЕ цифра /^\D+$/ Соответствует любому выражению, где нет цифр, например Петя
\s Пробел или табуляция (кроме перевода строки) /\s+/ Найдёт последовательность пробелов от одного и до бесконечности
\S Любой символ, кроме пробела или табуляции /\s+\S/ Найдёт последовательность пробелов, после которой есть хотя бы один другой символ
\b Граница слова /\bдом\b/ Найдёт только отдельные слова дом, но проигнорирует рядом
\B НЕ граница слова /\Bдом\b/ Найдёт только окночние слов, которые заканчиваются на дом
\R Любой перевод строки (Unix, Mac, Windows) /.*\R/ Найдёт строки, которые заканчиваются переводом строки

Нужно отметить, что спец. символы \w, \W, \b и \B не работают по умолчанию с юникодом (включая кириллицу). Для их правильной работы нужно указывать модификатор u. К сожалению, на окончание 2019 года JavaScript не поддерживает регулярные выражения для юникода даже с модификатором, поэтому в js эти мета-символы работают только для латиницы.

Ещё регулярные выражения поддерживают разные виды скобочек:

Выражение Описание Пример использования Результат
(…) Круглые скобки означают под-шаблон, который идёт в результат поиска /(Петя|Вася|Саша) любит Машу/ Найдёт всю строку и запишет воздыхателя Маши в результат поиска под номером 1
(?:…) Круглые скобки с вопросом и двоеточием означают под-шаблон, который НЕ идёт в результат поиска /(?:Петя|Вася|Саша) любит Машу/ Найдёт только полную строку, воздыхатель останется инкогнито
(?P<name>…) Задаёт имя под-шаблона /(?P<воздыхатель>Петя|Вася|Саша) любит Машу/ Найдёт полную строку, а воздыхателя запишет в результат под индексом 1 и ‘воздыхатель’
[abc] Квадратные скобки задают ЛЮБОЙ СИМВОЛ из последовательности (включая спец. символы \w, \d, \s и т.д.) /^[123]+$/ Соответствует любому выражению 323323123, но не 54321
[a-я0-9] Если внутри квадратных скобок указать минус, то это считается диапазоном /[A-Za-zА-Яа-яЁё0-9_]+/ Аналог /\w/ui для JavaScript
[abc-] Если минус является первым или последним символом диапазона, то это просто минус /[0-9+-]+/ Найдёт любое целое числое с плюсом или минусом (причём не обязательно, чтобы минус или плюс были спереди)
[^…] Квадратные скобки с «крышечекой» означают любой символ НЕ входящий в диапазон /[^a-zа-я0-9 ]/i Найдёт любой символ, который не является буквой, числом или пробелом
[[:class:]] Квадратные скобки в квадратных скобках задают класс символов (alnum, alpha, ascii, digit, print, space, punct и другие) /[^[:print:]]+/ Найдёт последовательность непечатаемых символов
{n} Фигурные скобки с одним числом задают точное количество символов /\w+н{2}\w+/u Найдёт слово, в котором две буквы н
{n,k} Фигурные скобки с двумя числами задают количество символов от n до k /\w+н{1,2}\w+/u Найдёт слово, в котором есть одна или две буквы н
{n,} Фигурные скобки с одним числом и запятой задают количество символов от n до бесконечности /\w+н{3,}\w+/u Найдёт слово, в котором н встречается от трёх и более раз подряд

Как правильно писать регулярные выражения ¶

Прежде, чем садиться и писать регулярно выраженного кракена, подумайте, что именно вы хотите сделать. Регулярное выражение должно начинаться с мысли «Я хочу найти/заменить/удалить то-то и то-то». Затем вам нужен исходный текст, который содержит как ПРАВИЛЬНЫЕ, так и НЕправильные данные. Затем вы открываете https://regex101.com/, вставляете текст и начинаете писать регулярное выражение. Этот замечательный инструмент укажет и покажет все ошибки, а также подсветит результаты поиска.

Для примера возьмём валидацию ip-адреса. Первая мысль должна быть: «Я хочу валидировать ip-адрес. А что такое ip-адрес? Из чего он состоит?». Затем нужен список валидных и невалидных адресов:


0.0.0.0 
0.1.2.3
99.99.99.99
199.199.199.199
255.255.255.255


01.01.01.01
.1.2.3
1.2.3.
255.0.0.256

Валидный адрес должен содержать четыре числа (байта) от 0 до 255. Если он содержит число больше 255, это уже ошибка. Если бы мы делали валидацию на каком-либо языке программирования, то можно было бы разбить выражение на четыре части и проверить каждое число отдельно. Но регулярные выражения не поддерживают проверки больше или меньше, поэтому придётся делать по-другому.

Для начала упростим задачу: будем валидировать не весь ip-адрес, а только один байт. А байт это всегда есть либо одно-, либо дву-, либо трёхзначное число. Для одно- и двузначного числа шаблон очень простой — любая цифра. А вот для трёхзначного числа первая цифра либо единица, либо двойка. Если первая цифра единица, то вторая и третья могут быть от нуля до девяти. Если же первая цифра двойка, то вторая может быть только от нуля до пяти. Если первая цифра двойка и вторая пятёрка, то третья может быть только от ноля до пяти. Давайте формализуем:


от 0 до 9              \d
от 10 до 99            [1-9]\d
от 100 до 199          1\d\d
от 200 до 249          2[0-4]\d
от 250 до 255          25[0-5]

Теперь, зная все диапазоны байта, можно объединить их в одно выражение через вертикальную палочку | (ИЛИ):

\b(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\b

Обратите внимание, что я использовал границу слова \b, чтобы искать полные байты. Пробуем регулярку в деле:

Как видим, все байты стали зелёненькими. Это значит, что мы на верном пути.

Осталось дело за малым: сделать так, чтобы искать четыре байта, а не один. Нужно учесть, что байты разделены тремя точками. То есть мы ищем три байта с точкой на конце и один без точки:

(\b(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\b\.){3}\b(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\b

Результат выглядит так:

Подсветились только валидные ip-адреса, значит регулярное выражение работает корректно.

Если бы я сразу начал писать валидацию всего адреса, а не отдельного байта, то с большой долей вероятности допустил бы ошибку. Скопления скобочек, палочек и точечек трудно воспринимаются на глаз, поэтому задачу надо обязательно упрощать.

Практическое применение регулярных выражений ¶

Регулярными выражениями можно пользоваться не только для валидации, но и для обработки данных, например, в блокноте. Вот практический пример такой обработки: скопировать номера регионов и перевести в формат PHP-массива.

Your browser does not support HTML5 video.

Ссылки ¶

Хорошая статья, мне понравилась. Оставлю отзыв!
Что-то статья не очень. Поругаю-ка я автора.


© 2020 Антон Прибора. При копировании материалов с сайта, пожалуйста, указывайте ссылку на источник.

Регулярные выражения (RegEx) — Документация TRegExpr 1.147

Вступление

Регулярные выражения — удобный способ описывать шаблоны текстов.

С помощью регулярных выражений вы можете проверять пользовательский ввод, искать некоторые шаблоны, такие как электронные письма телефонных номеров на веб-страницах или в некоторых документах и так далее.

Ниже приведена исчерпывающая шпаргалка по регулярных выражениям всего на одной странице.

Символы

Простые совпадения

Серия символов соответствует этой серии символов во входной строке.

RegEx Находит
foobar foobar

Непечатные символы (escape-коды)

Для представления непечатаемого символа в регулярном выражении используется \x с шестнадцатеричным кодом. Если код длиннее 2 цифр (более U+00FF), то он обрамляется в фигурные скобки.

RegEx Находит
\xAB символ с 2-значным шестнадцатеричным кодом AB
\x{AB20} символ с 1-4 значным шестнадцатеричным кодом AB20
foo\x20bar foo bar (обратите внимание на пробел в середине)

Существует ряд предопределенных escape-кодов для непечатных символов, как в языке C:

RegEx Находит
\t tab (HT/TAB), тоже что \x09
\n символ новой строки (LF), то же что \x0a
\r возврат каретки (CR), тоже что \x0d
\f form feed (FF), то же что \x0c
\a звонок (BEL), тоже что \x07
\e escape (ESC), то же что \x1b
\cA\cZ

chr(0) по chr(25).

Например \cI соответствует табуляции.

Также поддерживаются буквы в нижнем регистре «a»…»z».

Эскейпинг

Для представления спецсимволов (.+*?|\()[]{}^$), перед ними надо поставить \. Чтобы вставить сам обратный слэш его надо удвоить.

regex — сценарий оболочки. как извлечь строку с помощью регулярных выражений

Переполнение стека

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

.

Неограниченные регулярные выражения

Регулярные выражения — мощный механизм обработки текста. Вы можете использовать регулярные выражения для поиска шаблона в блоке текста, для замены фрагментов этого текста другими фрагментами текста и для управления строками различными другими тонкими и интересными способами.

Сама оболочка изначально не поддерживает регулярные выражения. Чтобы использовать регулярные выражения, вы должны вызвать внешний инструмент.

Некоторые инструменты, поддерживающие регулярные выражения, включают:

  • awk — язык сценариев сам по себе.Описано далее в How AWK-ward.

  • grep —Возвращает список строк, соответствующих выражению (или строк, не совпадающих с флагом -v ). Завершает работу со статусом истина (0), если совпадение произошло, или ложь (1), если совпадения не было.

  • perl —Язык сценариев с расширенной функциональностью регулярных выражений.

  • sed — инструмент, который выполняет замену текста на основе регулярных выражений.

Эти команды используются в этой главе.

Для целей этой главы вы должны вставить следующие строки текста в текстовый файл с окончанием строки UNIX (новая строка):

 У Марии был ягненок, 
 ее шерсть была белой, как снег, 
 и везде, куда Мэри шла, 
 ягненок обязательно должен был пойти. 
 Еще несколько строк, чтобы запутать: 
 У Мэриламба было немного.
 Это тест. Это всего лишь тест. 
 Мария была замужем. Рядом был ягненок. 
 Мэри, ягненок, и морозильная камера моего бакалейщика ... 
 Мэри, ягненок. 
 Выйти замуж за ягненка. 
 У Марии был ягненок, похожий на ягненка. 
 Я хочу шоколад на день святого Валентина.
 Эта строка содержит косую черту (/). 
 Эта строка содержит обратную косую черту (\). 
 Эта строка содержит квадратные скобки ([]). 
 Почему Мэри строчная? 
 А как насчет Мэри, Мэри и Мэри? 
 const people fox 
 постоянные черепахи медведь 
 созвездие Весов 
 Как насчет 9 * 9? 
 Быстрая коричневая лисица перепрыгнула через ленивую собаку.

Сохраните это в файл с именем poem.txt .

Где я могу использовать регулярные выражения?

Регулярные выражения чаще всего используются для фильтрации текста. Например, чтобы заменить каждое вхождение буквы "a" в строке на заглавную "A" , вы можете повторить строку и передать результат на sed следующим образом:

 echo " Это проверка, это всего лишь проверка »| sed 's / a / A / g' 

Вы также можете использовать регулярные выражения для поиска строк в файле или блоке текста с помощью команды grep .Например, чтобы найти слово «bar» в файле foo.txt , вы можете сделать следующее:

 grep «bar» foo.txt 
 # или 
 cat foo.txt | grep "bar" 

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

Типы регулярных выражений

Существует три основных типа регулярных выражений: базовые регулярные выражения, расширенные регулярные выражения и регулярные выражения Perl.В этой главе разделы указывают на области, в которых они расходятся. Этот раздел — просто краткое изложение различий. Подробнее см. В соответствующем разделе.

Основные регулярные выражения и расширенные регулярные выражения различаются в следующих областях:

  • В базовых регулярных выражениях используется обратная косая черта перед скобками группировки / захвата (и перед операторами вертикальной черты в этих скобках). Расширенные регулярные выражения — нет. Эти операторы описаны в разделе «Операторы группировки».

  • В базовых регулярных выражениях перед знаком плюс используется обратная косая черта, когда они используются для обозначения «одного или нескольких предыдущих символов или групп». Расширенные регулярные выражения — нет. Этот оператор описан в разделах «Подстановочные знаки» и «Операторы повторения».

  • Базовые регулярные выражения используют обратную косую черту перед вопросительным знаком, когда они используются для обозначения «ноль или один из предыдущих символов или групп». Расширенные регулярные выражения — нет. Этот оператор описан в разделах «Подстановочные знаки» и «Операторы повторения».

Регулярные выражения Perl эквивалентны расширенным регулярным выражениям с некоторыми дополнительными функциями:

  • Perl может (необязательно) использовать знак доллара вместо обратной косой черты для представления переменных в шаблонах подстановки, как описано в разделе Операторы и переменные захвата. .

  • Perl поддерживает скобки без фиксации, как описано в разделе «Скобки без захвата».

  • Порядок нескольких опций в круглых скобках может иметь значение, когда в игру вступают подстроки, как описано в разделе «Операторы группирования».

  • Perl позволяет включать буквальные квадратные скобки в любом месте класса символов, ставя перед ними обратную косую черту, как описано в разделе «Цитирование специальных символов».

  • Perl добавляет ряд дополнительных переключателей, которые эквивалентны определенным специальным символам и классам символов. Они описаны в ярлыках классов персонажей.

  • Perl поддерживает более широкий набор модификаторов. Они описаны в разделе «Использование модификаторов».

Синтаксис регулярных выражений

Основным форматом регулярных выражений является один из следующих, в зависимости от того, что вы пытаетесь сделать:

 / search_pattern / modifiers 
 command / search_pattern / modifiers 
 command / search_pattern / replace / modifiers 

Первый синтаксис — это базовый синтаксис поиска.В отсутствие префикса команды такое регулярное выражение возвращает строки, соответствующие шаблону поиска. В некоторых случаях косые черты могут быть (или должны быть) опущены — например, в аргументе шаблона для команды grep .

Второй синтаксис используется для большинства команд. В этой форме некоторые операции выполняются со строками, соответствующими шаблону. Это может быть форма сопоставления или может включать удаление частей строки, соответствующих шаблону.

Третий синтаксис используется для команд подстановки.Их можно рассматривать как более сложную форму поиска и замены.

Например, следующая команда ищет слово «тест» в указанном файле:

 # Выражение: / test / 
 grep 'test' poem.txt 

Примечание: Обратите внимание, что grep ожидает, что начальная и конечная косая черта в регулярном выражении будут удалены .

Доступность команд и флагов несколько различается в зависимости от варианта регулярного выражения и описывается в соответствующих разделах.Мэри «

Это соответствует слову» Мария «, но только тогда, когда оно появляется в начале строки. Точно так же следующее соответствует слову» лиса «, но только в конце строки :

 # Выражение: / fox $ / 
 grep "fox $" 

Другой распространенный метод изменения поведения соответствия регулярного выражения - использование флагов . Эти флаги, помещенные в конец регулярного выражения, могут изменить, разрешено ли регулярному выражению соответствовать нескольким строкам, является ли совпадение чувствительным к регистру или нечувствительным, и различные другие аспекты сопоставления.

Примечание: Различные инструменты поддерживают разные флаги, и не все флаги поддерживаются всеми инструментами. Инструмент командной строки grep использует флаги командной строки вместо флагов в самом выражении.

Наиболее часто используемый флаг - это глобальный флаг. По умолчанию сопоставляется только первое вхождение поискового запроса. В основном это вызывает беспокойство при выполнении замен. Глобальный флаг изменяет это так, что замена изменяет каждое совпадение в строке, а не только первое.

Например:

 # Выражение: s / Mary / Joe / 
 sed «s / Mary / Joe /» 

Это заменяет только первое вхождение «Мэри» на «Джо». . " Добавляя глобальный флаг к выражению, оно заменяет каждое вхождение, как показано в следующем примере:

 # Expression s / Mary / Joe / g 
 sed "s / Mary / Joe / g" <стихотворение.txt 

Подстановочные знаки и операторы повторения

Одним из наиболее распространенных способов улучшения поиска с помощью регулярных выражений является использование подстановочных знаков.

Подстановочный знак - это символ, который заменяет любой другой символ. В регулярных выражениях точка (. ) считается подстановочным знаком, поскольку соответствует любому одиночному символу. Например:

 # Выражение: /wa./ 
 grep 'wa.'poem.txt 

Соответствует строкам, содержащим как «было», так и «хочу», потому что точка может соответствовать любому символу.

Подстановочные знаки обычно комбинируются с операторами повторения для сопоставления строк, в которых известна только часть содержимого. Например, вы можете найти каждую строку, содержащую слово «Мария», а слово «ягненок» появится позже. Вы можете указать такое выражение:

 # Выражение: /Mary.*lamb/ 
 grep "Mary.* lamb "poem.txt 

Это ищет Мэри, за которой следует ноль или более символов, за которыми следует lamb.

Конечно, вы, вероятно, захотите хотя бы один символ между ними, чтобы избежать совпадений для строк, содержащих" Marylamb ". Наиболее распространенный способ решить эту проблему - использовать оператор плюс ( + ). Однако вы можете построить это выражение несколькими способами:

 # Выражение (базовое): /Mary.\+lamb/ 
 # Выражение (расширенное): / Mary.+ lamb / 
 # Выражение: /Mary..*lamb/ 
 grep "Mary. \ + lamb" poem.txt 
 grep -E "Mary. + lamb "poem.txt # расширенное регулярное выражение 
 grep" Mary .. * lamb "poem.txt 

Примечание: Внешний вид оператора плюса различается в зависимости от того, используете ли вы базовый или расширенный обычный выражения; в основных регулярных выражениях ему должна предшествовать обратная косая черта.

Первая точка в третьем выражении соответствует одному символу. Затем точка-звездочка соответствует нулю или более дополнительных символов. Таким образом, эти три утверждения эквивалентны.

Последний полезный оператор повторения - это оператор вопросительного знака (? ). Этот оператор соответствует нулю или одному повторению всего, что ему предшествует.

Примечание: Как и оператор «плюс», он отличается по внешнему виду в зависимости от того, используете ли вы базовые или расширенные регулярные выражения; в основных регулярных выражениях ему должна предшествовать обратная косая черта.

Например, если вы хотите сопоставить и Мэри, и Marry, вы можете использовать такое выражение:

 # Выражение (базовое): / Marr \? Y / 
 # Выражение (расширенное): / Marr? Y / 
 grep "Marr \? Y" poem.txt 
 grep -E "Marr? Y" poem.txt 

Знак вопроса заставляет предыдущее r быть необязательным, и, таким образом, это выражение соответствует строкам, содержащим либо «Мэри», либо «Жениться.

Таким образом, основные операторы подстановки и повторения:

  • период (. ) - wildcard; соответствует одному символу.

  • вопросительный знак ( \? или ? ) - соответствует 0 или 1 предыдущего символа, группировки или подстановочного знака. (Этот оператор различается в зависимости от того, используете ли вы базовые или расширенные регулярные выражения.)

  • звездочка ( * ) - соответствует нулю или более предыдущих символов, группировок или подстановочных знаков.

  • plus ( \ + или + ) - соответствует одному или нескольким предыдущим символам, группировкам или подстановочным знакам. (Этот оператор различается в зависимости от того, используете ли вы базовые или расширенные регулярные выражения.)

Классы и группы символов

Поиск по определенным ключевым словам может быть полезным, но часто этого недостаточно. Часто бывает полезно искать наличие или отсутствие ключевых символов в заданной позиции в строке поиска.

Например, предположим, что вам нужно, чтобы слова Мария и ягненок были в одном предложении.Для этого вам нужно разрешить только определенные символы появляться между двумя словами. Этого можно достичь с помощью классов символов.

Существует два основных типа классов символов: предопределенные классы символов и пользовательские или определяемые пользователем классы символов. Они описаны в следующих разделах.

Предопределенные классы символов

Большинство языков регулярных выражений поддерживают некоторую форму предопределенных классов символов. Когда они заключены в квадратные скобки, они определяют обычно используемые наборы символов.Наиболее широко поддерживаемый набор предопределенных классов символов - это классы символов POSIX:

  • [: alnum:] - все буквенно-цифровые символы (a-z, A-Z и 0-9).

  • [: alpha:] - все буквенные символы (a – z, A – Z).

  • [: blank:] - все пробелы в строке (пробелы или табуляции).

  • [: cntrl:] - все управляющие символы (ASCII 0–31).

  • [: digit:] - все номера.

  • [: graph:] - все буквенно-цифровые символы или знаки пунктуации.

  • [: lower:] - все строчные буквы (a-z).

  • [: print:] —все печатаемые символы (противоположность [: cntrl:] , то же, что и объединение [: graph:] и [: space:] ).

  • [: punct:] —все символы пунктуации

  • [: space:] —все символы пробела (пробел, табуляция, новая строка, возврат каретки, подача формы и вертикальная табуляция).(См. Примечание ниже о совместимости.)

  • [: upper:] —все буквы в верхнем регистре.

  • [: xdigit:] - все шестнадцатеричные цифры (0-9, a-f, A-F).

Например, следующий способ сопоставить любое предложение, содержащее Мэри и ягненок (но не если между ними есть знаки препинания):

 # Выражение: / Mary [[: alpha:] [: digit:] [: blank:]] [[: alpha:] [: digit:] [: blank:]] * lamb / 
 grep 'Мэри [[: alpha:] [: digit:] [: blank:]] [[: alpha:] [: digit:] [: blank:]] стихотворение * барашка.txt 

Примечание о совместимости: Не все инструменты полностью поддерживают классы символов POSIX. В частности:

  • Инструмент grep не поддерживает [: space:] , потому что этот класс символов включает символы разрыва строки, что не имеет смысла в инструменте, предназначенном для печати строк, соответствующих шаблону.

  • Инструмент sed принимает [: space:] , но обрабатывает его как [: blank:] по той же причине.

Настраиваемые классы символов

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

Например, если вы хотите разрешить только пробелы и буквы, вы можете создать класс символов, подобный этому:

 # Выражение: / Мэри [a-z A-Z] * lamb / 
 grep «Мэри [a-z A-Z] * lamb» стихотворение.txt 

В этом примере разрешены два диапазона (от « a » до « z » и « A » до « Z »), а также пробел. Таким образом, этому шаблону соответствует любая буква или пробел, а другие элементы (включая символ точки) - нет. Таким образом, эта строка соответствует первой строке стихотворения, но не соответствует более поздней строке, которая начинается со слов «Мария вышла замуж».

Однако этот шаблон также не соответствовал строке, содержащей запятую, что на самом деле не было намерением..] * lamb "poem.txt

Операторы группировки

Как упоминалось ранее, регулярные выражения также имеют понятие группировки. Цель группировки состоит в том, чтобы рассматривать несколько символов как единое целое, обычно для целей изменения этот объект с оператором повтора. Эта группировка выполняется с помощью круглых скобок или скобок в кавычках, в зависимости от используемого диалекта регулярного выражения.

Например, предположим, что вы хотите найти любую строку, содержащую слово «Мэри», за которым, возможно, следует слово «имел», за которым следует слово «а».Вы можете написать это выражение так:

 #Expression (Basic): / Mary \ (had \) \? A / 
 #Expression (Extended): / Mary (had)? A / 
 grep "Mary \ (had \) \? a "poem.txt 
 grep -E" Mary (had)? a "poem.txt 

Примечание: Оператор группировки и дополнительный оператор различаются в зависимости от какая программа обрабатывает регулярное выражение.Инструменты sed , awk и grep используют базовые регулярные выражения (по умолчанию), поэтому эти операторы должны быть заключены в кавычки. Любые инструменты, использующие расширенные регулярные выражения, используют голые операторы.

Также обратите внимание, что флаг -E включает расширенные регулярные выражения в grep .

Флаг для включения расширенных регулярных выражений в sed отличается в разных версиях инструмента. По этой причине вам следует по возможности использовать базовые регулярные выражения при работе с sed .

Вы также можете использовать синтаксис группировки для предоставления нескольких вариантов, любой из которых рассматривается как совпадение. Выражения, заключенные в круглые скобки, соответствуют любому из серии более мелких выражений, разделенных оператором вертикальной черты ( | ). Например, чтобы найти Мэри, ягненок или has, вы можете использовать это выражение:

 #Expression (Basic): / \ (Mary \ | had \ | lamb \) / 
 #Expression (Extended): / (Mary | had | lamb) / 
 grep '\ (Мэри \ | имела \ | овечку \)' стихотворение.txt 
 grep -E '(Mary | had | lamb)' poem.txt 

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

Например, следующие строки дают тот же результат:

 sed -E 's / (lamb | lamb,) / orange /' poem.txt 
 sed -E 's / (lamb, | lamb) / orange /' poem.txt 

Однако следующие строки этого не делают:

 perl -pi.bak -e 's / (lamb | lamb,) / orange /' 
 perl -pi.bak -e 's / (lamb, | lamb) / orange /' 

В Perl, когда входные данные содержат слово «ягненок», за которым следует запятая, обработчик регулярных выражений сначала сопоставляет слово «ягненок», поскольку это крайний левый вариант.Он заменяет его словом «оранжевый» и оставляет запятую. Во втором варианте, поскольку первой соответствует версия с запятой, запятая удаляется, если она есть.

Вы, конечно, также можете избежать этой проблемы, написав выражение как:

 perl -pi.bak -e 's / lamb,? / Orange /' 

Использование Пустые подвыражения

Иногда при работе с группами может оказаться необходимым включить необязательную группу.Может возникнуть соблазн написать такое выражение, как это:

 # Выражение (расширенное): / const (ant | ellation |) (. *) / 

Однако из-за странной причуды некоторые инструменты командной строки не распознают пустое подвыражение. Есть два способа решить эту проблему.

Самый простой способ - сделать всю группу необязательной, например:

 # Выражение (расширенное): / const (ant | ellation)? (. *) / 
 grep -E 'const (ant | ellation)? (.*) '

Как вариант, после вертикальной черты можно вставить пустое выражение.

 # Выражение (расширенное): / const (ant | ellation | ()) (. *) / 
 grep -E "const (ant | ellation | ()) (. *)" Poem .txt 

Примечание: Если вы смешиваете захват с группировкой, этот метод создает пустой захват, который заканчивается в буфере после буфера захвата для этой группы (подробнее об этом в разделе «Операторы и переменные захвата»).

Использование специальных символов в кавычках

Как было показано в предыдущих разделах, ряд символов имеет особое значение в регулярных выражениях. Например, классы символов заключены в квадратные скобки, а символы тире и вставки имеют особое значение. Вы можете спросить, как найти одного из этих персонажей. Вот здесь-то и появляется кавычка.

В регулярных выражениях некоторые небуквенные символы могут иметь особое значение в зависимости от контекста. Чтобы рассматривать эти символы как обычные символы, вы можете использовать перед ними символ обратной косой черты ( \ ).Это также означает, что символ обратной косой черты является особенным в любом контексте, поэтому, чтобы соответствовать буквальному символу обратной косой черты, вы должны заключить его в кавычки со второй обратной косой чертой.

Однако есть одно исключение. Чтобы сделать закрывающую скобку членом класса символов, вы не заключаете ее в кавычки. Вместо этого вы делаете его первым персонажем в классе.

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

Например, для поиска любой строки, содержащей обратную косую черту или закрывающую скобку, вы можете использовать следующее регулярное выражение:

 # Выражение: / [] \\] / 
 grep '[] \\]' poem.txt 

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

.Учебное пособие по регулярным выражениям Linux

: пример Grep Regex

  • Home
  • Testing

      • Back
      • Agile Testing
      • BugZilla
      • Cucumber
      • 000 J2000
      • 000 J2000 Testing
      • 9000
      • Назад
      • JUnit
      • LoadRunner
      • Ручное тестирование
      • Мобильное тестирование
      • Mantis
      • Почтальон
      • QTP
      • Назад
      • Центр качества (ALM)
      • Центр качества (ALM)
      • Управление тестированием
      • TestLink
  • SAP

      • Назад
      • 9000 3 ABAP

      • APO
      • Начинающий
      • Базис
      • BODS
      • BI
      • BPC
      • CO
      • Назад
      • CRM
      • Crystal Reports
      • Crystal Reports
      • FICO3
      • Заработная плата
      • Назад
      • PI / PO
      • PP
      • SD
      • SAPUI5
      • Безопасность
      • Менеджер решений
      • Successfactors
      • SAP Back Tutorials
      • 9007
          • Apache
          • AngularJS
          • ASP.Net
          • C
          • C #
          • C ++
          • CodeIgniter
          • СУБД
          • JavaScript
          • Назад
          • Java
          • JSP
          • Kotlin
          • Linux
          • Linux
          • Kotlin
          • Linux
          • js

          • Perl
          • Назад
          • PHP
          • PL / SQL
          • PostgreSQL
          • Python
          • ReactJS
          • Ruby & Rails
          • Scala
          • SQL
          • 000

          • SQL
          • 000

            0003 SQL

            000

            0003 SQL

            000

          • UML
          • VB.Net
          • VBScript
          • Веб-службы
          • WPF
      • Обязательно учите!

          • Назад
          • Бухгалтерский учет
          • Алгоритмы
          • Android
          • Блокчейн
          • Business Analyst
          • Создание веб-сайта
          • CCNA
          • Облачные вычисления
          • 0003 COBOL
          • 000 Compiler
              9000 Встроенный

            • 000 9000 Compiler
            • Ethical Hacking
            • Учебники по Excel
            • Программирование на Go
            • IoT
            • ITIL
            • Jenkins
            • MIS
            • Сети
            • Операционная система
            • 0003
            • Назад
            • Управление проектами Обзоры
            • Salesforce
            • SEO
            • Разработка программного обеспечения
            • VB A
        • Big Data

            • Назад
            • AWS
            • BigData
            • Cassandra
            • Cognos
            • Хранилище данных
            • 0003

            • HBOps
            • 0003

            • HBOps
            • 0003

            • MicroStrategy
            • MongoDB

        .

        regex - регулярные выражения в сценарии оболочки tcsh

        Переполнение стека

        1. Около
        2. Продукты

        3. Для команд
        1. Переполнение стека
          Общественные вопросы и ответы

        2. Переполнение стека для команд
          Где разработчики и технологи делятся частными знаниями с коллегами

        3. Вакансии
          Программирование и связанные с ним технические возможности карьерного роста

        4. Талант
          Нанимайте технических специалистов и создавайте свой бренд работодателя

        5. Реклама
          Обратитесь к разработчикам и технологам со всего мира

        .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *