Рубріки: Теория

Что такое Grep? Практические примеры использования

Денис Бородовский

Grep — один из полезнейших инструментов системного администратора, этакий «швейцарский нож», помогающий специалисту решать множество повседневных рутинных задач. Чаще всего его используют при поиске строк и шаблонов в группе файлов или в подпапках. Далее в этой статье рассмотрим эту команду более подробно.

1. Что такое Grep?

Grep (Global Regular Expression Print) — это утилита командной строки, которая устанавливается по умолчанию почти во всех дистрибутивах Linux, BSD и UNIX (в силу своей популярности она даже портирована для Windows). GNU и Free Software Foundation распространяют Grep как часть набора своих инструментов, поставляемых с открытым исходным кодом.

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

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

Есть два способа применения Grep, имеющие свои особенности:

  1. Можно использовать для поиска заданного файла или файлов в системе (включая рекурсивный поиск по подпапкам).
  2. Также Grep может работать в конвейерном режиме фильтра, принимая входные данные (обычно через канал) от другой команды (или серии предшествующих команд).

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

Обратите внимание на курсы разработчиков от наших партнеров школы Robot Dreams и Mate Academy. Это идеальное начало вашего пути в IT.

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

Регулярное выражение «regex» или «regexp» — это способ указания универсального шаблона для поиска (определенного набора символов или слов) в тексте, применяемого к входным переменным, для поиска всех вхождений, соответствующих этому шаблону. Регулярные выражения расширяют возможности осмысленной обработки текстового содержимого, особенно в сочетании с другими командами.

Обычно они включаются в команду Grep в следующем формате:

grep [options] [regexp] [filename]

GNU Grep использует версию регулярных выражений GNU, очень похожую (но не идентичную) на регулярные выражения стандарта POSIX. Фактически, большинство разновидностей регулярных выражений очень похожи, но имеют различия в escape-символах, метасимволах или специальных операторах.

GNU Grep имеет два набора функций регулярных выражений: базовый и расширенный. В основных регулярных выражениях мета-символы ?, +, {, |, ( и ) теряют свой особый смысл (их использование мы рассмотрим ниже). Как упоминалось ниже, чтобы переключиться на использование расширенных регулярных выражений, вам необходимо добавить параметр -E в Grep-команду.

Регулярное выражение принято заключать в одинарные кавычки, чтобы оболочка (Bash или другие) не пыталась интерпретировать и расширять выражение перед запуском Grep-процесса. Например, если пара косых кавычек ( ` — часто называемых backticks) в регулярном выражении не заключена в стандартные одинарные кавычки, это приведет к тому, что текст между ними будет выполняться как подпроцесс Bash.

Далее, если вдруг это окажется допустимой командой, то текст, возвращаемый ею, займет место регулярного выражения в параметрах командной строки, передаваемых Grep! А это не совсем то, что мы хотим.

Мощность regex склонна порождать подобные весьма труднопонимаемые ошибки, поэтому при работе с Grep необходима высокая ясность мышления.

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

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

Теперь перейдем к практическим примерам использования рассматриваемой команды. Чтобы лучше понять результаты ее применения, я создал простой текстовый файл, в котором мы будем выполнять поиск с помощью 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

4. Использование регулярных выражений

[highload@clone ~]$ grep 'c.r' testfile
to carry out few regular expressions

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

  • Большинство символов, включая все буквы и цифры, на самом деле являются регулярными выражениями, соответствующими друг другу.
  • Любой метасимвол (имеющий особое значение для Grep, как «.» в примере выше) можно заключить в кавычки, поставив перед ним обратную косую черту. Это заставит Grep относиться к нему как к обычному члену выражения.
[highload@clone ~]$ grep 'c\.r' testfile
[highload@clone ~]$

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

  • Точка ( . ) соответствует любому одиночному символу.
  • ? означает, что предыдущий элемент является необязательным и, если он найден, будет сопоставлен не более одного раза.
  • * означает, что предыдущий элемент будет найден ноль или более раз.
  • + означает, что предыдущий элемент будет найден один или более раз.
  • {n} означает, что предыдущий элемент соответствует ровно n раз, {n,} — что элемент соответствует n или более раз, {n,m} — предыдущий элемент встречается не менее n раз, но не более m раз, а {,m} значит, что предыдущий элемент соответствует не более m раз.

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

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

5. Классы символов в регулярных выражениях

Инструмент «класс символов» — одна из наиболее гибких и часто используемых функций регулярных выражений. Есть два основных способа использования классов символов: указать список символов (например, [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 перечислено больше таких именованных классов, специально созданных для удобства пользователя.

6. Якоря

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

[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

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

Как упоминалось ранее, если вы не заключите в одинарные кавычки шаблон поиска, переданный в 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, помогающей администратору при работе с файлами.

Несколько полезных видеороликов по теме:

 

 

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023