Grep — один из полезнейших инструментов системного администратора, этакий «швейцарский нож», помогающий специалисту решать множество повседневных рутинных задач. Чаще всего его используют при поиске строк и шаблонов в группе файлов или в подпапках. Далее в этой статье рассмотрим эту команду более подробно.
Grep (Global Regular Expression Print) — это утилита командной строки, которая устанавливается по умолчанию почти во всех дистрибутивах Linux, BSD и UNIX (в силу своей популярности она даже портирована для Windows). GNU и Free Software Foundation распространяют Grep как часть набора своих инструментов, поставляемых с открытым исходным кодом.
Grep быстро и эффективно находит строку в заданном файле, используя для этого довольно хитроумные и невероятно гибкие критерии. Хотя в реальной жизни большинство задач решаемых при помощи рассматриваемой команды просты, существует множество более сложных ее применений, о которых не знает большинство людей.
В основе этой утилиты лежит расширенный синтаксис регулярных выражений, добавленный в UNIX сразу после оригинальной реализации этой концепции в 1981 году.
Есть два способа применения Grep, имеющие свои особенности:
Таким образом, сочетая эти подходы, точка приложения Grep становится универсальной: можно искать файлы в директориях по сложным критериям, отфильтровывать нужные процессы в памяти, искать подстроки в содержимом одного (или сразу нескольких) файлов, как-то обрабатывать вывод (результаты работы) других команд через пайпы, парсить по определенным критериям лог-файлы и т.д.
Обратите внимание на курсы разработчиков от наших партнеров школы Robot Dreams и Mate Academy. Это идеальное начало вашего пути в IT.
Регулярное выражение
Обычно они включаются в команду Grep в следующем формате:
grep [options] [regexp] [filename]
GNU Grep использует версию регулярных выражений GNU, очень похожую (но не идентичную) на регулярные выражения стандарта POSIX. Фактически, большинство разновидностей регулярных выражений очень похожи, но имеют различия в escape-символах, метасимволах или специальных операторах.
GNU Grep имеет два набора функций регулярных выражений: базовый и расширенный. В основных регулярных выражениях мета-символы ?
, +
, {
, |
, (
и )
теряют свой особый смысл (их использование мы рассмотрим ниже). Как упоминалось ниже, чтобы переключиться на использование расширенных регулярных выражений, вам необходимо добавить параметр -E
в Grep
-команду.
Регулярное выражение принято заключать в одинарные кавычки, чтобы оболочка (Bash
или другие) не пыталась интерпретировать и расширять выражение перед запуском Grep-процесса. Например, если пара косых кавычек ( `
— часто называемых backticks) в регулярном выражении не заключена в стандартные одинарные кавычки, это приведет к тому, что текст между ними будет выполняться как подпроцесс Bash
.
Далее, если вдруг это окажется допустимой командой, то текст, возвращаемый ею, займет место регулярного выражения в параметрах командной строки, передаваемых Grep! А это не совсем то, что мы хотим.
Мощность regex склонна порождать подобные весьма труднопонимаемые ошибки, поэтому при работе с Grep необходима высокая ясность мышления.
Вы также можете заключить регулярное выражение в двойные кавычки — в этом случае можно использовать в regex переменные среды, подставляемые перед вызовом Grep. Это может быть очень полезно, а может оказаться неприятным сюрпризом, если, опять же, вы не до конца понимаете, что делаете.
Теперь перейдем к практическим примерам использования рассматриваемой команды. Чтобы лучше понять результаты ее применения, я создал простой текстовый файл, в котором мы будем выполнять поиск с помощью Grep. Файл содержит следующие строки:
Hi this is test file to carry out few regular expressions practical with grep 123 456 Abcd ABCD
Теперь, используя эту текстовую болванку, разберемся с часто используемыми Grep-операциями:
1. Поиск без учета регистра ( grep -i
):
[highload@clone ~]$ grep -i 'abcd' testfile Вернет: Abcd ABCD
Как вы можете видеть, метка -i
заставляет механизм поиска «abcd
» возвращать совпадения с разными регистрами символов.
2. Поиск по всему слову ( grep -w
):
[highload@clone ~]$ grep -w 'test' testfile Вернет: is test file
Этот тип поиска возвращает только строки, в которых искомое сочетание букв является отдельным целым словом, а не частью большего слова.
3. Рекурсивный поиск по подпапкам ( grep -r <pattern> <path>
):
[highload@clone ~]$ grep -r '456' /root/ /root/testfile:Year is 2021
4. Обратный поиск ( grep -v
):
[highload@clone ~]$ grep -v 'practical' testfile
Вернет:
Hi this is test file to carry out few regular expressions 123 456 Abcd ABCD
Поиск вернет все строки в файле, кроме строки, содержащей слово «practical
».
4. Метка -L
выводит имена файлов, которые НЕ содержат совпадений с вашим шаблоном поиска. Сами несовпадения не выводятся, а выводятся только названия файлов.
highload@clone ~]$ grep -r -L "Network" /var/log/* /var/log/anaconda.log /var/log/anaconda.syslog /var/log/audit/audit.log /var/log/boot.log
Противоположный метке-L
флажок -l
или --files-with-matches
, выводит только имена тех файлов, которые действительно содержат совпадения с вашим шаблоном поиска.
5. Выведем дополнительные (замыкающие) строки контекста после match
( grep -A <NUM>
):
[highload@clone ~]$ grep -A1 '123' testfile
Выведет:
123 456 Abcd
Для каждой строки, соответствующей поиску, Grep печатает эту строку, а также следующую строку после совпадения. Метка -A
изменяет количество дополнительных строк в выводе.
6. Перед совпадением выведем дополнительные (ведущие) строки контекста ( grep -B <NUM>)
:
[highload@clone ~]$ grep -B2 'Abcd' testfile
Выведет:
practical with grep 123 456 Abcd
7. Выводим дополнительные (ведущие и замыкающие) строки контекста до и после совпадения( grep -C <NUM>)
:
[highload@clone ~]$ grep -C2 'carry' testfile
Выведет:
this is test file to carry out few regular expressions practical with grep 123 456
Можно заметить, что выведены строки до и после единственного совпадения, найденного в файле. Если найдено несколько совпадений, Grep вставляет символ — между каждой группой строк (каждым совпадением и строками его контекста).
8. Выводим имя файла для каждого совпадения ( grep -H <pattern> filename)
:
[highload@clone ~]$ grep -H 'a' testfile
Выведет:
testfile:to carry out few regular expressions testfile:practical with grep
9. Теперь давайте немного по-другому запустим поиск:
[highload@clone ~]$ cat testfile | grep -H 'a'
Стандартный вывод:
(standard input):to carry out few regular expressions (standard input):practical with grep
Искомый поток, запущенный через конвейер из предыдущей команды в цепочке, передается на обработку в Grep. При использовании метки -H в имени файла, отображается (standard input)
.
10. Запуск в «тихом» режиме ( grep -q)
При запуске с меткой -q grep
устанавливает свое возвращаемое значение (также известное как статус вывода), чтобы отразить результат — найдено совпадение или нет. Такой вид команды, как правило, используется в сценариях с проверкой на конкретное совпадение. Статус возврата 0 (ноль) указывает, что совпадение найдено; 1 означает, что совпадений не найдено.
[highload@clone ~]$ grep -q '2010' testfile [highload@clone ~]$ echo $? 1 [highload@clone ~]$ grep -q '456' testfile [highload@clone ~]$ echo $? 0
[highload@clone ~]$ grep 'c.r' testfile to carry out few regular expressions
В приведенном выше примере символ точка «.
» заменяет любой символ в искомом сочетании букв. В написанном выше выражении, например, найдется подстрока «car»
в слове «carry»
. У Grep есть мощный механизм сопоставления регулярных выражений, о котором надо знать несколько важных моментов:
.
» в примере выше) можно заключить в кавычки, поставив перед ним обратную косую черту. Это заставит Grep относиться к нему как к обычному члену выражения.[highload@clone ~]$ grep 'c\.r' testfile [highload@clone ~]$
За регулярным выражением может следовать один из нескольких операторов повторения:
( . )
соответствует любому одиночному символу.?
означает, что предыдущий элемент является необязательным и, если он найден, будет сопоставлен не более одного раза.*
означает, что предыдущий элемент будет найден ноль или более раз.+
означает, что предыдущий элемент будет найден один или более раз.{n}
означает, что предыдущий элемент соответствует ровно n
раз, {n,}
— что элемент соответствует n или более раз, {n,m}
— предыдущий элемент встречается не менее n раз, но не более m раз, а {,m}
значит, что предыдущий элемент соответствует не более m раз.Операторы повторения являются частью расширенного синтаксиса регулярных выражений GNU Grep, поэтому для их эффективного использования не забудьте добавить параметр в команду -E
.
Рассмотрим несколько примеров регулярных выражений и разберемся, как они работают.
Инструмент «класс символов» — одна из наиболее гибких и часто используемых функций регулярных выражений. Есть два основных способа использования классов символов: указать список символов (например, [aeiou]
это список гласных символов) или диапазон (например [m-t]
, который автоматически расширяется до [mnopqrst]
).
Диапазоны — это удобство, которое избавляет от необходимости вводить всю последовательность символов. Класс символов также может включать в себя список специальных символов, но их нельзя использовать в качестве диапазона.
Пример: давайте найдем сочетание из одиннадцати букв алфавита, содержащее только строчные символы. Регулярное выражение для поиска будет выглядеть так: [a-z]{11}
. Сюда также нужно добавить оператор повторения — опцию -E
. Давайте посмотрим, как это будет выглядеть применительно к нашему тестовому файлу:
[highload@clone ~]$ grep -E '[a-z]{11}' testfile
Выведет:
to carry out few regular expressions
Здесь «expressions
» — единственная строка из 11 символов в нижнем регистре в файле, поэтому ее и выведет на экран.
Существует довольно много классов символов, часто используемых в регулярных выражениях, представленных в виде именованных классов. Например:
[:lower:]
— именованный класс для рассмотренного нами класса строчных букв [a-z]
.[:upper:]
— для заглавных букв от A до Z.[:alpha:]
— для всех буквенных символов, эквивалентных [:lower:]
и [:upper:]
вместе взятых.[:digit:]
— это цифры от 0 до 9.[:alnum:]
— это буквенно-цифровые символы — комбинация [:alpha:]
и [:digit:]
.В руководстве Grep перечислено больше таких именованных классов, специально созданных для удобства пользователя.
Якорь ^
указывает, что совпадение выражению должно быть в начале строки:
[highload@clone ~]$ grep '^th' testfile this
Якорь $
указывает, что совпадение выражению должно быть в конце строки:
[highload@clone ~]$ grep 'i$' testfile Hi
Оператор \<
привязывает образец для поиска — к началу слова:
[highload@clone ~]$ grep '\<fe' testfile to carry out few regular expressions
Оператор \>
привязывает наш поисковый шаблон к концу слова:
[highload@clone ~]$ grep 'le\>' testfile is test file
Сочетание символов \b
(граница слова) может быть использовано вместо \<
и \>
для обозначения начала и конца слова:
[highload@clone ~]$ grep -e '\breg' testfile to carry out few regular expressions
Еще рассмотрим оператор (чередования) |
, являющийся частью одной из расширенных функций регулярных выражений. Шаблон поиска, содержащий этот оператор отдельно, соответствует частям по обе стороны от него. Если один из них найден, строка, содержащая его, является совпадением. Части сами по себе могут быть сложными регулярными выражениями, поэтому вы можете проверять каждую строку в файле на наличие нескольких совпадений за один проход.
[highload@clone ~]$ grep -E 'hi|bc' testfile this Abcd
Как упоминалось ранее, если вы не заключите в одинарные кавычки шаблон поиска, переданный в Grep, он изменится. Это также можно сделать намеренно, когда именно это и нужно — давайте рассмотрим несколько примеров.
[root@clone ~]# grep "$HOME" /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin
Здесь мы специально используем двойные кавычки, чтобы оболочка Bash заменяла переменную среды $HOME
фактическим значением переменной (в данном случае /root
). Таким образом, Grep ищет в файле /etc/passwd
текст /root
и выявляет две совпадающие строки.
Напоследок кратко рассмотрим полезные практические примеры использования grep с учетом всех ранее обсуждаемых возможностей.
1. Фильтрация найденных командой grep файлов
Предположим, вам надо отфильтровать содержимое файла /etc/apache2/sites-available/default-ssl
, содержащего закомментированные строки. Это можно сделать так:
# grep –v "#" /etc/apache2/sites-available/default-ssl
2. Обнаружение всех файлов с расширением .mp3
Если вам нужно узнать сколько на вашем ПК музыкальных файлов(*.mp3
) созданных исполнителем ABC, не являющихся ремиксом — используйте в grep
команду find
:
# find . –name "*.mp3" | grep –i ABC | grep –vi "remix"
3. Подсчет числа строк, содержащих искомое выражение:
# ifconfig | grep –c inet6
флаг -с
позволяет вести поиск в обоих направлениях.
4. Указание номера искомой строки в файле
При помощи флага -n можно не только вывести необходимые строки, но и их номера.
# grep –n "main" setup.py
5. Рекурсивный поиск строки по всем каталогам
Добавление флага -r запускает рекурсивный поиск:
# grep –r "function" *
6. Совпадения в архивах Gzip
Gzip (GNU Zip) — популярная Linux-утилита, предназначенная для сжатия и декомпрессии файлов. Чтобы выполнить поиск в сжатых архивах — воспользуйтесь командой zgrep
(которая входит в состав этого архиватора, поставляя свою версию Grep):
# zgrep –i error /var/log/syslog.2.gz
В статье мы разобрались с наиболее часто встречающимися примерами использования команды для сложного поиска — Grep, помогающей администратору при работе с файлами.
Несколько полезных видеороликов по теме:
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…