Использование команды grep в Linux: как искать шаблоны, строки в файлах

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

Что такое grep

grep – это консольная утилита для поиска строк по заданному образцу. Она просматривает текст построчно и выводит только те строки, которые соответствуют шаблону.

Название часто расшифровывают как global regular expression print, но исторически оно произошло от команды редактора ed: g/re/p (g – globally, re – regular expression, p – print). Имя утилиты – это и есть та самая команда, вынесенная в отдельную программу.

Утилита работает в трех основных режимах:

  • поиск в одном или нескольких файлах;
  • поиск в потоке данных, который передается через конвейер (pipe) от другой команды;
  • рекурсивный поиск по всем файлам внутри директории.

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

grep --version

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

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

grep [опции] "шаблон" [файл...]

Где:

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

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

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

Самый простой случай – найти строки со словом error в файле лога:

grep "error" access.log

grep выведет все строки, в которых встречается error, подсвечивая совпадения (если включена цветная подсветка).

С помощью grep поиск можно вести сразу по нескольким файлам, перечислив их через пробел:

grep "error" access.log error.log

В этом случае перед каждой найденной строкой grep укажет имя файла, в котором она найдена.

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

ps aux | grep nginx

Здесь grep получает данные не из файла, а из вывода предыдущей команды.

В выводе ps aux | grep nginx почти всегда оказывается лишняя строка – сам процесс grep nginx, который в момент поиска тоже виден в списке процессов. Чтобы исключить его, применяют небольшую хитрость с символьным классом:

ps aux | grep [n]ginx

Шаблон [n]ginx совпадает со строкой nginx, но сама команда в списке процессов выглядит как grep [n]ginx и под этот шаблон уже не подходит. Как альтернатива – специализированная утилита pgrep nginx, которая ищет процессы по имени и этой проблемы лишена.

Основные опции grep

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

  • игнорирование регистра: -i

По умолчанию grep различает заглавные и строчные буквы. Флаг -i отключает чувствительность к регистру, и тогда Error, ERROR и error будут считаться совпадениями:

grep -i "error" access.log
  • инверсия поиска: -v

Флаг -v выводит строки, которые не содержат шаблон. Удобно, когда нужно исключить лишнее. Например, показать все строки конфига, кроме пустых и закомментированных:

 grep -vE "^#|^$" nginx.conf
  • номера строк: -n

Опция -n добавляет к каждой найденной строке ее номер в файле. Это упрощает дальнейшую работу с файлом:

grep -n "server_name" nginx.conf
  • строки контекста: -A, -B, -C

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

  1. -A N (after) – показать N строк после совпадения;
  2. -B N (before) – показать N строк до совпадения;
  3. -C N (context) – показать N строк до и после совпадения.

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

grep -A3 "error" app.log

Показать совпадение вместе с двумя строками перед ним:

grep -B2 "error" app.log

А -C покажет окружение с обеих сторон сразу:

grep -C3 "error" app.log

Если в файле несколько совпадений, grep отделяет их блоки строкой с --.

  • подсчет совпадений: -c

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

grep -c "404" access.log

Команда вернет только число строк, в которых встретился код 404.

  • вывод только совпавшей части: -o

По умолчанию grep выводит строку целиком, даже если шаблон совпал лишь с ее частью. Флаг -o оставляет в выводе только сам фрагмент, совпавший с шаблоном, а каждое совпадение печатается на отдельной строке. Это удобно, когда нужно извлечь конкретные данные, а не строки целиком – например, вытащить из лога все IP-адреса в начале строк:

grep -oE "^[0-9.]+" access.log
  • список файлов с совпадениями: -l

Флаг -l выводит не сами строки, а имена файлов, в которых есть хотя бы одно совпадение:

grep -l "password" *.php

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

  • рекурсивный поиск: -r и -R

Опция -r запускает поиск по всем файлам в указанной директории и во всех вложенных папках:

grep -r "TODO" /var/www/site/

Разница между -r и -R касается обработки символических ссылок при рекурсивном обходе. Если grep натыкается на symlink внутри подкаталогов, то -r такие ссылки игнорирует, а -R по ним переходит. При этом по ссылке, явно указанной в самой команде, перейдут оба варианта.

  • поиск целых слов: -w

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

grep -w "cat" file.txt
  • совпадение по всей строке: -x

Если -w ограничивает совпадение целым словом, то -x требует, чтобы шаблону соответствовала вся строка целиком. Это удобно при точечной проверке конфигов или списков:

grep -x "127.0.0.1 localhost" /etc/hosts
  • поиск по нескольким шаблонам сразу: -e

Когда нужно искать несколько разных строк за один проход, необязательно собирать сложное регулярное выражение. Можно перечислить шаблоны через флаг -e:

grep -e "404" -e "500" access.log
  • поиск по фиксированной строке: -F

По умолчанию grep трактует шаблон как регулярное выражение, поэтому символы ., *, [, $ и другие имеют специальное значение. Если же нужно найти строку буквально, со всеми спецсимволами как есть, используйте флаг -F (fixed strings):

grep -F "192.168.0.1" access.log

Здесь точки будут восприняты как обычные точки, а не как «любой символ». Это избавляет от необходимости экранировать каждый спецсимвол и заметно ускоряет поиск на больших файлах. Раньше для этого существовала отдельная команда fgrep, но сейчас она считается устаревшей – рекомендуется применять grep -F.

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

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

Базовые регулярные выражения (BRE)

Это режим по умолчанию. Основные метасимволы:

  • ^ – начало строки;
  • $ – конец строки;
  • . – любой одиночный символ;
  • * – повторение предыдущего символа ноль или более раз;
  • [...] – любой символ из указанного набора.

Несколько примеров: 

  • Найти строки, начинающиеся со слова Error:
grep "^Error" error.log
  • Найти строки, заканчивающиеся на ;:
grep ";$" nginx.conf
  • Найти пустые строки:
grep "^$" file.txt

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

В базовом режиме символы +, ?, {}, | и () нужно экранировать обратным слешем. Чтобы этого избежать, используйте флаг -E. Он включает расширенный синтаксис. Раньше для этого существовала отдельная команда egrep, но сейчас рекомендуется применять именно grep -E.

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

  • + – повторение один или более раз;
  • ? – ноль или одно повторение;
  • {n,m} – от n до m повторений;
  • | – логическое «или»;
  • () – группировка.

Например, найти строки с кодами ошибок 404 или 500:

grep -E "404|500" access.log

Найти слова color и colour одновременно:

grep -E "colou?r" file.txt

Perl-совместимые регулярные выражения (PCRE)

Флаг -P включает наиболее мощный синтаксис регулярных выражений, совместимый с языком Perl. Он поддерживает такие конструкции, как \d (цифра), \w (буква, цифра или подчеркивание), \s (пробельный символ), а также «ленивые» квантификаторы и опережающие проверки.

Например, извлечь все email-адреса:

grep -oP "[\w.-]+@[\w.-]+\.\w+" file.txt

Стоит учитывать, что режим -P поддерживается не во всех системах, так как он опирается на отдельную библиотеку PCRE.

Объединение grep в цепочки

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

Например, найти в логе строки с кодом 404, относящиеся к запросам изображений в формате PNG:

grep "404" access.log | grep "\.png"

Сначала первый grep отбирает строки с 404, а затем второй из них оставляет только те, что содержат .png. Такой подход часто оказывается проще, чем составлять одно сложное регулярное выражение.

Если возникнут вопросы о работе VPS-серверов, напишите нам, пожалуйста, тикет из панели управления аккаунта (раздел «Помощь и поддержка»), а если вы захотите обсудить наши продукты с коллегами по цеху и сотрудниками Beget – ждем вас в нашем сообществе в Telegram.