В чем заключается поиск по шаблону linux

Обновлено: 07.07.2024

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

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

В своей простейшей форме, когда тип регулярного выражения не указан, grep интерпретирует шаблоны поиска как базовые регулярные выражения. Чтобы интерпретировать шаблон как расширенное регулярное выражение, используйте параметр -E (или --extended-regexp ).

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

Буквальные совпадения

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

В этом примере строка «bash» представляет собой базовое регулярное выражение, состоящее из четырех буквальных символов. Это указывает grep искать строку, в которой сразу после grep «b» идут «a», «s» и «h».

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

Чтобы игнорировать регистр при поиске, используйте параметр -i (или --ignore-case ).

Важно отметить, что grep ищет шаблон поиска как строку, а не слово. Итак, если вы искали «gnu», grep также напечатает строки, в которых «gnu» встроено в слова большего размера, например, «cygnus» или «magnum».

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

Якорь

Символ ^ (каретка) соответствует пустой строке в начале строки. В следующем примере строка «linux» будет соответствовать только в том случае, если она встречается в самом начале строки.

Символ $ (доллар) соответствует пустой строке в начале строки. Чтобы найти строку, заканчивающуюся строкой «linux», вы должны использовать:

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

Соответствующий одиночный символ

Выражения в скобках

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

Вместо того, чтобы помещать символы по одному, вы можете указать диапазон символов внутри скобок. Выражение диапазона создается путем указания первого и последнего символов диапазона, разделенных дефисом. Например, [aa] эквивалентно [abcde] а 3 эквивалентно [123] .

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

grep также поддерживает предопределенные классы символов, заключенные в скобки. В следующей таблице показаны некоторые из наиболее распространенных классов символов:

Квантификатор Классы персонажей
[:alnum:] Буквенно-цифровые символы.
[:alpha:] Буквенные символы.
[:blank:] Пробел и табуляция.
[:digit:] Цифры.
[:lower:] Строчные буквы.
[:upper:] Заглавные буквы.

Полный список всех классов персонажей можно найти в руководстве по Grep .

Квантификаторы

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

Квантификатор Описание
* Сопоставьте предыдущий элемент ноль или более раз.
? Соответствует предыдущему элементу ноль или один раз.
+ Сопоставьте предыдущий элемент один или несколько раз.
Сравните предыдущий элемент ровно n раз.
Сопоставьте предыдущий элемент не менее n раз.
Соответствовать предыдущему элементу не более m раз.
Сопоставьте предыдущий элемент от n до m раз.

Символ * (звездочка) соответствует предыдущему элементу ноль или более раз. Следующее будет соответствовать «right», «sright», «ssright» и так далее:

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

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

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

Символ + (плюс) соответствует предыдущему элементу один или несколько раз. Следующее будет соответствовать «sright» и «ssright», но не «right»:

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

Следующее соответствует всем целым числам, содержащим от 3 до 9 цифр:

Чередование

Термин «чередование» представляет собой простое «ИЛИ». Оператор чередования | (pipe) позволяет вам указать различные возможные совпадения, которые могут быть буквальными строками или наборами выражений. Этот оператор имеет самый низкий приоритет среди всех операторов регулярных выражений.

В приведенном ниже примере мы ищем все вхождения слов fatal , error и critical в файле ошибок журнала Nginx :

Если вы используете расширенное регулярное выражение, то оператор | не следует экранировать, как показано ниже:

Группировка

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

Следующий пример соответствует как «бесстрашный», так и «меньший». ? квантификатор делает группу (fear) необязательной:

Специальные выражения обратной косой черты

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

Выражение Описание
b Сопоставьте границу слова.
< Соответствует пустой строке в начале слова.
> Соответствует пустой строке в конце слова.
w Подберите слово.
s Подберите пробел.

Следующий шаблон будет соответствовать отдельным словам «abject» и «object». Он не будет соответствовать словам, если вложен в слова большего размера:

Выводы

Регулярные выражения используются в текстовых редакторах, языках программирования и инструментах командной строки, таких как grep , sed и awk . Знание того, как создавать регулярные выражения, может быть очень полезным при поиске текстовых файлов, написании сценариев или фильтрации вывода команд.

Если у вас есть какие-либо вопросы или отзывы, не стесняйтесь оставлять комментарии.

Иногда может понадобится найти файл, в котором содержится определённая строка или найти строку в файле, где есть нужное слово. В Linux всё это делается с помощью одной очень простой, но в то же время мощной утилиты grep. С её помощью можно искать не только строки в файлах, но и фильтровать вывод команд, и много чего ещё.

В этой инструкции мы рассмотрим, как выполняется поиск текста в файлах Linux, подробно разберём возможные опции grep, а также приведём несколько примеров работы с этой утилитой.

Что такое grep?

Команда grep (расшифровывается как global regular expression print) - одна из самых востребованных команд в терминале Linux, которая входит в состав проекта GNU. Секрет популярности - её мощь, она даёт возможность пользователям сортировать и фильтровать текст на основе сложных правил.

Утилита grep решает множество задач, в основном она используется для поиска строк, соответствующих строке в тексте или содержимому файлов. Также она может находить по шаблону или регулярным выражениям. Команда в считанные секунды найдёт файл с нужной строчкой, текст в файле или отфильтрует из вывода только пару нужных строк. А теперь давайте рассмотрим, как ей пользоваться.

Синтаксис grep

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

$ grep [опции] шаблон [имя файла. ]

$ команда | grep [опции] шаблон

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

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

Опции

Давайте рассмотрим самые основные опции утилиты, которые помогут более эффективно выполнять поиск текста в файлах grep:

Все самые основные опции рассмотрели и даже больше, теперь перейдём к примерам работы команды grep Linux.

Примеры использования

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

Поиск текста в файлах

В первом примере мы будем искать пользователя User в файле паролей Linux. Чтобы выполнить поиск текста grep в файле /etc/passwd введите следующую команду:

grep User /etc/passwd

В результате вы получите что-то вроде этого, если, конечно, существует такой пользователь:

А теперь не будем учитывать регистр во время поиска. Тогда комбинации ABC, abc и Abc с точки зрения программы будут одинаковы:

grep -i "user" /etc/passwd

Вывести несколько строк

Например, мы хотим выбрать все ошибки из лог-файла, но знаем, что в следующей строчке после ошибки может содержаться полезная информация, тогда с помощью grep отобразим несколько строк. Ошибки будем искать в Xorg.log по шаблону "EE":

grep -A4 "EE" /var/log/xorg.0.log

Выведет строку с вхождением и 4 строчки после неё:

grep -B4 "EE" /var/log/xorg.0.log

Выведет целевую строку и 4 строчки до неё:

grep -C2 "EE" /var/log/xorg.0.log

Выведет по две строки с верху и снизу от вхождения.

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

Регулярные выражения grep - очень мощный инструмент в разы расширяющий возможности поиска текста в файлах. Для активации этого режима используйте опцию -e. Рассмотрим несколько примеров:

grep "^Nov 10" messages.1

Nov 10 01:12:55 gs123 ntpd[2241]: time reset +0.177479 s
Nov 10 01:17:17 gs123 ntpd[2241]: synchronized to LOCAL(0), stratum 10

Поиск в конце строки - спецсимвол "$":

grep "terminating.$" messages

Jul 12 17:01:09 cloneme kernel: Kernel log daemon terminating.
Oct 28 06:29:54 cloneme kernel: Kernel log daemon terminating.

Найдём все строки, которые содержат цифры:

grep "7" /var/log/Xorg.0.log

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

Рекурсивное использование grep

grep -r "mydomain.com" /etc/apache2/

В выводе вы получите:

grep -r "zendsite" /etc/apache2/
/etc/apache2/vhosts.d/zendsite_vhost.conf: ServerName zendsite.localhost
/etc/apache2/vhosts.d/zendsite_vhost.conf: DocumentRoot /var/www/localhost/htdocs/zendsite
/etc/apache2/vhosts.d/zendsite_vhost.conf: <Directory /var/www/localhost/htdocs/zendsite>

Здесь перед найденной строкой указано имя файла, в котором она была найдена. Вывод имени файла легко отключить с помощью опции -h:

grep -h -r "zendsite" /etc/apache2/

ServerName zendsite.localhost
DocumentRoot /var/www/localhost/htdocs/zendsite
<Directory /var/www/localhost/htdocs/zendsite>

Поиск слов в grep

Когда вы ищете строку abc, grep будет выводить также kbabc, abc123, aafrabc32 и тому подобные комбинации. Вы можете заставить утилиту искать по содержимому файлов в Linux только те строки, которые выключают искомые слова с помощью опции -w:

grep -w "abc" имя_файла

Поиск двух слов

Можно искать по содержимому файла не одно слово, а два сразу:

egrep -w 'word1|word2' /path/to/file

Количество вхождений строки

Утилита grep может сообщить, сколько раз определённая строка была найдена в каждом файле. Для этого используется опция -c (счетчик):

grep -c 'word' /path/to/file

C помощью опции -n можно выводить номер строки, в которой найдено вхождение, например:

grep -n 'root' /etc/passwd

Инвертированный поиск в grep

Команда grep Linux может быть использована для поиска строк в файле, которые не содержат указанное слово. Например, вывести только те строки, которые не содержат слово пар:

grep -v пар /path/to/file

Вывод имени файла

Вы можете указать grep выводить только имя файла, в котором было найдено заданное слово с помощью опции -l. Например, следующая команда выведет все имена файлов, при поиске по содержимому которых было обнаружено вхождение primary:

grep -l 'primary' *.c

Цветной вывод в grep

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

grep --color root /etc/passwd


Выводы

Вот и всё. Мы рассмотрели использование команды grep для поиска и фильтрации вывода команд в операционной системе Linux. При правильном применении эта утилита станет мощным инструментом в ваших руках. Если у вас остались вопросы, пишите в комментариях!

Команда Grep в Linux (Поиск текста в файлах)

Команда grep означает «глобальная печать регулярных выражений», и это одна из самых мощных и часто используемых команд в Linux.

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

grep Синтаксис команды

Синтаксис grep команды следующий:

Элементы в квадратных скобках не являются обязательными.
  • OPTIONS - Ноль или более вариантов. Grep включает в себя ряд параметров, которые контролируют его поведение.
  • PATTERN - Шаблон поиска.
  • FILE - Ноль или более имен входных файлов.

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


Поиск строки в файлах

Основное использование grep команды - поиск строки (текста) в файле.

Например, чтобы отобразить все строки, содержащие строку bash из /etc/passwd файла, вы должны выполнить следующую команду:


Вывод должен выглядеть примерно так:

Если строка содержит пробелы, вам необходимо заключить ее в одинарные или двойные кавычки:


Инвертировать (исключить) совпадение

Чтобы отобразить линии, которые не соответствуют шаблону, используйте параметр -v (или --invert-match ).

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

Использование Grep для фильтрации выходных данных команды

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

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


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

Рекурсивный поиск

Для рекурсивного поиска шаблона, grep используйте -r опцию (или --recursive ). Когда эта опция используется, grep будет выполняться поиск по всем файлам в указанном каталоге, пропуская символические ссылки, которые встречаются рекурсивно.

Чтобы перейти по всем символическим ссылкам , вместо этого -r используйте -R опцию (или --dereference-recursive ).

Вот пример, показывающий, как искать строку baks.dev во всех файлах в /etc каталоге:


Вывод будет включать совпадающие строки с префиксом полного пути к файлу:

Если вы используете -R опцию, grep перейдите по всем символическим ссылкам:

Обратите внимание на последнюю строку вывода ниже. Эта строка не печатается, когда grep вызывается -r из-за того, что файлы в sites-enabled каталоге Nginx являются символическими ссылками на файлы конфигурации внутри sites-available каталога.

Показывать только имя файла

Чтобы подавить grep вывод по умолчанию и печатать только имена файлов, содержащих сопоставленный шаблон, используйте параметр -l (или --files-with-matches ).

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


Вывод будет выглядеть примерно так:

-l Вариант обычно используется в сочетании с рекурсивной опции -R :


Поиск без учета регистра

По умолчанию учитывается grep регистр. Это означает, что прописные и строчные символы рассматриваются как разные.

Чтобы игнорировать регистр при поиске, grep используйте -i опцию (или --ignore-case ).

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


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


Указание «Зебра» будет соответствовать «Зебра», «ZEbrA» или любой другой комбинации прописных и строчных букв для этой строки.

Поиск полных слов

При поиске строки grep будут отображаться все строки, в которых строка встроена в более крупные строки.

Например, если вы ищете «gnu», все строки, где «gnu» встроен в более крупные слова, такие как «cygnus» или «magnum», будут совпадать:

Чтобы вернуть только те строки, в которых указанная строка представляет собой целое слово (заключенное не в словах), используйте параметр -w (или --word-regexp ).

Символов слова включают в себя буквенно - цифровые символы ( a-z , A-Z и 0-9 ) и подчеркивание ( _ ). Все остальные символы рассматриваются как несловесные символы.

Если вы выполните ту же команду, что и выше, включая -w опцию, grep команда вернет только те строки, которые gnu включены в качестве отдельного слова.

Показать номера строк

Опция -n (или --line-number ) указывает grep показывать номер строки, содержащей строку, которая соответствует шаблону. Когда эта опция используется, grep печатает совпадения на стандартный вывод с префиксом номера строки.

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


Вывод ниже показывает нам, что совпадения находятся в строках 10423 и 10424.

Количество совпадений

Чтобы напечатать количество совпадающих строк в стандартный вывод, используйте параметр -c (или --count ).

В приведенном ниже примере мы подсчитываем количество учетных записей, которые имеют /usr/bin/zsh оболочку.


Скрытый режим

-q (Или --quiet ) говорит , grep чтобы работать в скрытом режиме , чтобы не показывать ничего на стандартный вывод. Если совпадение найдено, команда завершается со статусом 0 . Это полезно при использовании grep в сценариях оболочки, где вы хотите проверить, содержит ли файл строку, и выполнить определенное действие в зависимости от результата.

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


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

GNU Grep имеет три набора функций регулярных выражений : базовый, расширенный и Perl-совместимый.

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

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

Используйте ^ символ (каретка), чтобы соответствовать выражению в начале строки. В следующем примере строка kangaroo будет соответствовать только в том случае, если она встречается в самом начале строки.

Используйте $ символ (доллар), чтобы соответствовать выражению в конце строки. В следующем примере строка kangaroo будет соответствовать только в том случае, если она встречается в самом конце строки.

Используйте . символ (точка), чтобы соответствовать любому отдельному символу. Например, для сопоставления всего, что начинается с kan двух символов и заканчивается строкой roo , вы можете использовать следующий шаблон:

Используйте [ ] (скобки) для соответствия любому отдельному символу, заключенному в скобки. Например, найдите строки, содержащие accept или « accent , вы можете использовать следующий шаблон:

Используется [^ ] для соответствия любому отдельному символу, не заключенному в скобки. Следующий шаблон будет соответствовать любой комбинации строк, содержащих co(any_letter_except_l)a , например coca , cobalt и так далее, но не будет совпадать со строками, содержащими cola ,


Чтобы избежать специального значения следующего символа, используйте \ символ (обратный слеш).

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

Чтобы интерпретировать шаблон как расширенное регулярное выражение, используйте параметр -E (или --extended-regexp ). Расширенные регулярные выражения включают в себя все основные метасимволы, а также дополнительные метасимволы для создания более сложных и мощных шаблонов поиска. Ниже приведены некоторые примеры:

Сопоставьте и извлеките все адреса электронной почты из данного файла:

Сопоставьте и извлеките все действительные IP-адреса из данного файла:

-o Опция используется для печати только строку соответствия.

Поиск по шаблону нескольких строк

Два или более шаблонов поиска могут быть объединены с помощью оператора ИЛИ | .

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

В приведенном ниже примере мы ищем все вхождения слов fatal , error и critical в журнале Nginx файл ошибки:


Если вы используете опцию расширенного регулярного выражения -E , оператор | не должен быть экранирован, как показано ниже:


Печать строк перед сопоставлением

Чтобы напечатать определенное количество строк перед сопоставлением строк, используйте параметр -B (или --before-context ).

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


Печать строк после сопоставления

Чтобы напечатать определенное количество строк после сопоставления строк, используйте параметр -A (или --after-context ).

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


Вывод

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

Если вы считаете, что умеете готовить, то может, вы знаете о том, как сделать суфле или пахлаву, а может — и не знаете. Но есть кое-что такое, чему вы, вероятно, научились, просто готовя разные блюда. Например, вы, скорее всего, можете вскипятить воду, можете правильно разбить яйцо, можете поджарить мясо. Если говорить о работе в Linux или Unix, то тут тоже можно сделать похожие наблюдения. Возможно, вы не знаете о том, как установить сервер Wayland, или о том, как написать модуль ядра. Но есть определённые базовые навыки, вроде работы с файлами или редактирования текстов, которые люди осваивают независимо от того, чем они занимаются, навыки, которые помогают им в самых разных ситуациях. Один из навыков, полезных в самых разных ситуациях, овладение которым часто вызывает определённые сложности, это — умение пользоваться регулярными выражениями. Многие программы используют их в качестве средства описания шаблонов поиска чего-либо. Обычно — для поиска данных в строках, например — в файлах с каким-то текстом.


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

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

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

Но grep — это далеко не единственная программа, использующая регулярные выражения. Среди других программ, в которых применяются регулярные выражения, можно отметить awk, sed, perl, разные редакторы, вроде Vim и emacs. Этот список можно продолжать ещё очень долго. Столь широкая распространённость регулярных выражений ведёт к тому, что их можно увидеть, например, в неких настройках программ, они встречаются даже в веб-приложениях, где используются для расширения возможностей этих приложений.

В различных системах может присутствовать не только grep, но и другие, похожие утилиты, вроде egrep. Например, в моей системе имеется команда egrep, которая представляет собой «обёртку» вокруг grep. Она вызывает grep с передачей этой утилите опции командной строки -E , что воздействует на вид регулярных выражений, с которыми работает grep. В результате тут я, если не отмечено иное, буду говорить именно о egrep.

Поиск строк по шаблонам и классы

Взгляните на следующий пример:


Эта команда просмотрит файл somefile.txt и найдёт следующие строки:

▍Точка — это универсальный символ

Строки со словом Dog при этом найдены не будут. Дело в том, что регулярные выражения, по умолчанию, чувствительны к регистру символов. Если бы этим все возможности регулярных выражений и ограничивались, тогда ничего особенно интересного в них бы не было. Но их возможности гораздо шире. Например, точка играет роль чего-то, напоминающего шаблон, соответствующий любому символу. Поэтому регулярное выражение d.g соответствует и строке dog , и строке dig (и, раз уж мы об этом говорим, строке d$g ).

▍Экранирование символов

Если точка — это «универсальный символ», то как тогда найти строки, в которых есть точка? Для этого можно воспользоваться экранированием символов с использованием обратной косой черты. Этот приём можно использовать в применении к любым специальным символам. В результате регулярное выражение d\.g найдёт строку d.g и ничего другого. Правда, тут стоит помнить о том, что символ обратной косой черты может иметь особый смысл в различных программах. Например, посмотрите на этот сеанс работы с egrep.

Использование обратной косой черты

Тут есть одна особенность. Оболочка интерпретирует последовательность символов \. как обычную точку. Она не считает обратную косую черту частью регулярного выражения, воспринимая её как экранирующий символ, используемый в самой оболочке. Для того чтобы, всё же, передать egrep конструкцию \. , нужно экранировать символ обратной косой черты ещё одним таким же символом ( \\ ). Именно это и сделано во втором примере. Экранирование специальных символов может оказаться непростой задачей, конкретные действия зависят от используемой оболочки. Если вы применяете bash, то вам, возможно, достаточно будет заключить регулярное выражение в одинарные или двойные кавычки. Но даже при таком подходе остаются актуальными правила, касающиеся обратной косой черты.

▍Классы символов

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


Эта команда найдёт строки вроде X000V и Z123V . Этот приём часто используют для того чтобы сделать поиск нечувствительным к регистру символов (например, используя конструкции вроде [aA] или [a-zA-Z] ).

Кроме того, можно описывать классы символов, которые не должны содержаться в искомых строках. Делается это с использованием символа ^ . Например, класс [^XYZ] соответствует любому символу кроме X , Y и Z . Если нужно найти тире ( - ), то этот знак должен идти в начале группы. А вот если нужно найти символ ^ — его не надо ставить в начало группы. Так как порядок символов в группе не играет роли при её обработке, проблем это не вызовет. В результате, например, если нас интересуют все цифры, а так же символы - и ^ , то соответствующее регулярное выражение будет выглядеть так:

Повторы

Мы уже знаем о том, как найти слова dog , dig , dug и d$g . Это очень хорошо, но лишь этим возможности регулярных выражений не ограничиваются. А именно, при использовании регулярных выражений можно описывать последовательности повторяющихся символов. Можно сделать и так, чтобы некий символ был бы необязательным. Например, вот регулярное выражение, которое найдёт и слово bar , и слово bear : be?ar .

Часто надо сделать так, чтобы некий шаблон мог бы присутствовать в находимых строках в одном экземпляре, но мог бы и полностью в них отсутствовать. Может понадобиться и поиск повторяющихся символов, а заодно и выявление их полного отсутствия. Иногда надо, чтобы регулярное выражение реагировало бы на нечто, имеющееся в строке в единственном экземпляре или повторяющееся несколько раз. Предположим, что нужно найти в файле некоего лога числа с десятичной точкой, перед которыми может присутствовать дефис, символизирующий знак «минус», а может и не присутствовать. В этой ситуации можно использовать конструкцию -?1+\.?3* . Для того чтобы лучше понимать подобные конструкции, полезным может оказаться представление их в виде диаграмм.

Графическое представление регулярного выражения (создано с помощью Regexper )

Этому шаблону будут соответствовать числа -25.2 , 33. , 17.125 . Знак + указывает на то, что в строке должна быть, как минимум, одна цифра, но их может быть и больше. Символ * соответствует любому количеству цифр, в том числе — и нулевому. Обратите внимание на то, что символ десятичной точки нуждается в экранировании. У этого регулярного выражения есть одна интересная особенность. Оно будет работать и без экранирования символа десятичной точки. Ведь точка соответствует любому символу. Но при таком подходе найдено будет и нечто вроде 14X2 , то есть, в нашем случае, неправильно оформленное число.

▍Продвинутое описание повторов

В более продвинутых регулярных выражениях для описания повторов можно пользоваться фигурными скобками, указывая в них то, сколько раз может повторяться шаблон. Некоторые инструменты требуют экранирования символов фигурных скобок. При работе с grep экранировать их не нужно. То есть, например, если нужно найти четыре буквы, записанные в нижнем регистре, можно воспользоваться конструкцией [a-z] .

Безусловно, то же самое можно описать и так: [a-z][a-z][a-z][a-z] . Применение фигурных скобок лишь ускоряет ввод соответствующих конструкций. В фигурных скобках, кроме того, можно указывать диапазон количества повторов, задавая его нижнюю и верхнюю границы. Например — так: [a-z] . Это соответствует последовательностям длиной от двух до четырёх символов. Это — то же самое, что и [a-z][a-z][a-z]?[a-z]? .

▍В разных программах обработка повторов различается

Для grep достаточно факта нахождения совпадения с регулярным выражением. При работе с некоторыми другими инструментами в расчёт принимается совпадение с наибольшим или наименьшим количеством символов. Например, регулярное выражение abc* , применённое к строке, содержащей abccccc , может обнаружить только символы ab , а может и найти совпадение со всей этой последовательностью символов. Это зависит от конкретного инструмента (и иногда — от настроек этого инструмента, например — от опций командной строки). Но об этом стоит помнить. Разные инструменты работают по-разному в деле обработки множественных совпадений. Например, при применении шаблона X к строке XyyX может быть найден только первый X , но могут быть найдены и оба символа. Но для grep, опять же, это значения не имеет. Этот инструмент интересует нахождение в строке хотя бы одного совпадения с регулярным выражением.

Привязка шаблона к началу и к концу строки

Возможно, вы обратили внимание на то, что в вышеприведённых примерах совпадение с шаблоном может быть найдено в любой части строки. Но, если нужно, можно привязать шаблон к началу строки, воспользовавшись символом ^ , или к концу строки — с помощью символа $ . Например, такая конструкция поможет найти пустые строки: ^ *$. А если нужно, чтобы подобные строки начинались бы с символа табуляции, можно поступить так: ^[ \t]*$ .

Последовательность \t , как и в языке C, означает знак табуляции. В зависимости от того, какой именно инструмент используется, в вашем распоряжении могут оказаться и другие особые символы. Вот, например, как искать строки, первым непробельным символом которых является % : ^[ \t]*% .

Группировка

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


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


Графическое представление регулярного выражения (создано с помощью Regexper )

Это — не то же самое, что ab?c?d , так как такое регулярное выражение отреагирует на последовательность символов acd . Кроме того, в регулярных выражениях можно использовать символ | , играющий роль оператора ИЛИ . Например, конструкция a|b найдёт символ a или символ b , что не особенно отличается от возможностей конструкции [ab] .

Но если объединить эту возможность с группировкой — может получиться нечто весьма полезное. Например, конструкция вида (dog)|(cat) способна найти и dog , и cat . В некоторых программах группировка способна помочь в выделении интересующих разработчика фрагментов кода, или может позволить выполнять продвинутую замену текстов. Например, в некоторых программах можно выполнить поиск с использованием регулярного выражения id=(1)+ , а в строке замены можно использовать конструкцию \1 для того чтобы сослаться на любое число, совпавшее с выражением, указанным в скобках. То, как именно это будет выглядеть, зависит от конкретной программы. Например, в некоторых программах может применяться нечто вроде &1 .

В чём польза регулярных выражений? Зачем их изучать?

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

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


В первой строке кода осуществляется поиск текстов, содержащих пробел и букву C в конце строки. Подпрограмма match получает число в matchres[1] . При таком подходе она сочтёт подходящей и бессмыслицу вроде -…C , но мы можем предположить, что в наших данных ничего такого нет. Возможно, ситуацию улучшит использование такого регулярного выражения: -?8\.?3* (правда, обратите внимание на то, что для использования такого регулярного выражения с grep, из-за использования в его начале символа - , нужно будет воспользоваться опцией -e ). Преобразование выполняет функция gensub . Как видите, для решения задачи понадобилось немало знаний о регулярных выражениях.

Варианты регулярных выражений

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

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

Часто в регулярных выражениях используются сокращённые конструкции для описания чего-то вроде цифр и пробельных символов. Это полезная возможность, так как она повышает переносимость регулярных выражений. Например, конструкция [:digit:] является заменой для 8 . В некоторых программах для той же цели используются особые управляющие символы, вроде \d . Здесь можно найти таблицу, в которой имеются описания распространённых систем регулярных выражений.

Инструменты для отладки регулярных выражений

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

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

Перевод статьи «How to Search for a File in Linux and Unix with Recursive Find».


Photo by Rabie Madaci on Unsplash

Для поиска заданного шаблона в файле или группе файлов в системах UNIX и Linux используется инструмент командной строки grep .

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

Как использовать grep

Если команде grep не заданы никакие дополнительные опции, она осуществляет поиск заданного шаблона в файле (или файлах). Синтаксис команды следующий:

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

Чтобы искать указанный текст во всех файлах директории, можно использовать астериск (*).

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

Возьмем пример. Допустим, у нас есть файл (назовем его grep.txt), содержащий такие строки:

Команда, приведенная ниже, будет искать все вхождения слова you в этом файле.

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

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

Использование команды grep с дополнительными опциями

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

Обратите внимание: если бы в одной строке было найдено два совпадения с шаблоном, в выводе все равно было бы 2 . Команда подсчитывает число строк, а не число вхождений.

Вы заметили, что мы также использовали опцию -n ? Все верно, вы запросто можете комбинировать разные опции в одной команде.

По умолчанию grep ищет все строки, в которых встречается заданный шаблон (в том числе, если заданная последовательность символов является частью более длинного слова). Таким образом, grep yo grep.txt и grep you grep.txt дадут одинаковые результаты, потому что в слове «you» содержится «yo» (с «ou» ситуация будет аналогичной).

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

По умолчанию grep выводит всю строку, в которой найдено совпадение с искомым шаблоном. Если добавить опцию -o , будет выводиться только само совпадение, строка за строкой. Например:

Совпадение с шаблоном было найдено в строке № 2. Благодаря опции -A 1 мы получили одну строку перед строкой № 2, а благодаря опции -B 1 — одну строку после нее. (Число указывает, сколько конкретно строк до и после вхождения шаблона нужно вывести. Т.е., могло быть -A 5 и -B 2 . — Прим. ред. Techrocks).

Есть еще опия -C (--context) , эквивалентная одновременному использованию опций -A и -B . Число, указанное при опции -C , будет касаться количества строк и до, и после вхождения. (Т.е., если вы укажете grep you grep.txt -C 5 , это будет эквивалентно grep you grep.txt -A 5 -B 5 . — Прим. ред. Techrocks).

По умолчанию grep не ищет в шаблон в директориях. При попытке сделать это вы получите ошибку «Is a directory». Опция -R делает возможным поиск в директориях и вложенных директориях. Например:


Photo by Anthony Martino on Unsplash

Применение регулярных выражений в шаблонах

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

1. ^шаблон — строка должна начинаться с заданного шаблона

При таком определении шаблона grep будет искать строки, которые начинаются со слова (слов), стоящего после символа ^ . Например:

2. шаблон$ — строка должна заканчиваться указанным шаблоном

При такой записи grep будет искать строки, оканчивающиеся на слово (слова) в шаблоне. Например:

Заключение

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

Конечно, мы рассмотрели не все опции этой команды. С остальными вы можете ознакомиться в руководстве (man grep).

Читайте также: