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

АМ
Александр Мельников
31 января 2020

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

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

/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

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

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

Остались вопросы? Задайте их нашему эксперту и получите квалифицированную помощь