Команда grep
встроена во множество дистрибутивов операционной системы Linux. Она запускает утилиту, которая выполняет поиск либо конкретного файла с указанным текстом, либо конкретной строки внутри файла с указанными символами.
Название «grep» является акронимом «global regular expression print». Некоторые разработчики говорят просто «грепать» — то есть искать какое-либо регулярное выражение в большом объеме файлов.
На вход команде можно подавать не только директории с файлами для поиска, но и текстовый вывод других команд, тем самым фильтруя его.
В этой статье мы подробно рассмотрим использование команды grep
:
Схематически команда выглядит так:
grep [флаги] выражение [<путь к директории или файлу>]
Вместо файлов и папок на вход можно передать вывод другой команды:
другая_команда | grep [флаги] выражение
Это помогает отфильтровывать наиболее важную информацию среди прочей менее важной в момент вывода из других программ.
Что касается регулярных выражений, то они — основа команды grep
. Они необходимы для создания шаблонов поиска.
Забегая вперед, у регулярных выражений есть два уровня — базовый (Basic Regular Expressions, BRE) и расширенный (Extended Regular Expressions, ERE). Чтобы включить последний, необходимо использовать флаг -E
.
Тонкости использования утилиты grep
лучше всего разбирать на реальных примерах — в виде небольших задач. Далее мы последовательно рассмотрим основные варианты поиска строк внутри файлов.
В примерах этой инструкции использовалась операционная система Ubuntu 22.04, размещенная в облаке Timeweb Cloud.
Чтобы создать аналогичный облачный сервер, нужно сперва авторизоваться в Timeweb Cloud.
Страница авторизации Timeweb Cloud
После этого в панели управления нужно перейти на страницу «Облачные серверы» и нажать на кнопку «Создать».
Откроется конфигуратор облачного сервера. Настройка довольна простая — около 8 параметров. Самый основной — операционная система. Нужно выбрать Ubuntu 22.04.
Страница конфигурации облачного сервера
Далее жмем создать «Заказать» и оказывается на странице управления облачным сервером. Пару минут нужно подождать, пока сервер подготовится и запустится.
После этого можно подключиться к удаленному хосту по SSH через консольный терминал вашей системы на основе тех данных, которые указаны на главной странице управления сервером.
Для этого понадобится IPv4-адрес и Root-пароль.
Справа на главной странице облачного сервера есть данные для удаленного подключения
Теперь, когда облачный сервер сконфигурирован, создан и запущен, можно протестировать работу команды grep
на его мощностях.
cloud
После настройки операционной системы нужно немного настроить ее окружение. В частности файловую систему, с которой мы будем работать.
Давайте сперва подготовим набор текстовых файлов, внутри которых впоследствии мы будем выполнять поиск совпадений с помощью утилиты grep
.
Создадим отдельную папку под файлы:
mkdir files
После чего перейдем в нее:
cd files
Здесь мы разместим файл, который будет содержать текст на русском языке:
sudo nano russian1
Содержимым выступит отрывок стихотворения Пушкина:
У лукоморья дуб зелёный
Златая цепь на дубе том
И днём и ночью кот учёный
Всё ходит по цепи кругом
И еще один файл на английском:
sudo nano english1
Содержимым выступит отрывок из произведения «Гордость и предубеждение», которое написала Джейн Остин:
However little known the feelings or views of such a man may be on his first entering a neighbourhood, this truth is so well fixed in the minds of the surrounding families, that he is considered as the rightful property of some one or other of their daughters.
Еще один файл будет содержать простой код на JavaScript:
sudo nano code1
Содержимое такое:
const number1 = 2;
const number2 = 4;
const sum = number1 + number2;
console.log('Сумма чисел ' + number1 + ' и ' + number2 + ' равна ' + sum);
Проверим наличие созданных файлов:
ls
Консоль должна вывести такой список:
code1 english1 russian1
Отлично! Именно на этих файлах мы и протестируем работу команды grep
.
Давайте попробуем найти все артикли «the» в файле с английским текстом:
grep 'the' english1
В консоли появится найденные элементы, в которых красным цветом будут помечены все вхождения «the».
Однако есть одна проблема — grep
также указал на слова «other» и «their», которые не являются артиклями.
Чтобы найти только артикли, можно использовать специальный флаг -w
. Благодаря нему будет выполнять поиск только целых слов, без вхождений указанного набора символов:
grep -w 'the' english1
Теперь консольный терминал выделит красным только те «the», которые не являются частью другого слова.
Можно усложнить регулярное выражение, добавив специальный оператор. Например, мы можем найти только строки, оканчивающиеся определенным набором символов:
grep 'ый$' russian1
Консоль выведет только те строки, в которых есть указанные вхождения, — их она подсветит красным цветом:
У лукоморья дуб зелёный
И днём и ночью кот учёный
Можно активировать расширенные регулярные выражения, указав флаг -E
. Расширенный режим добавляет несколько новых символов, делая поиск еще более гибким.
|
символ повторяется один или более раз |
|
символ повторяется ноль или более раз |
|
символ повторяется от n до m раз |
|
разделитель, объединяющий разные паттерны |
Небольшой пример использования расширенных регулярных выражений:
grep -E '[а-я]+ом$' ./*
Здесь указывается, что после слога «ом» должен быть конец строки, а перед ним должен идти один или более символ на кириллице.
Вывод будет таким:
./russian1:Златая цепь на дубе том
./russian1:Всё ходит по цепи кругом
Стоит упомянуть, что регулярные выражения, на которых основана утилита grep
, — довольно общий и универсальный формальный язык, используемый в различных языках программирования и операционных системах.
Поэтому в данной инструкции рассматриваются лишь часть его возможностей.
С помощью флага -n
можно добавить номер строки во время вывода найденных вхождений:
grep -n 'ый$' russian1
Вывод будет таким:
1:У лукоморья дуб зелёный
3:И днём и ночью кот учёный
С помощью флага -i
можно искать вхождения, не учитывая регистр символов:
grep -i 'И' russian1
Вывод будет таким:
И днём и ночью кот учёный
Всё ходит по цепи кругом
Мы могли бы не указывать этот флаг:
grep 'И' russian1
В этом случае было бы найдено лишь одно вхождение:
И днём и ночью кот учёный
Часто нужно найти только целые слова, а не вхождения указанных символов. Для этого используется флаг -w
.
Мы можем модифицировать предыдущий поиск, задействовав сразу два флага:
grep -iw 'И' russian1
Вывод будет содержать строку с двумя полными вхождениями обоих регистров:
И днём и ночью кот учёный
Результаты поиска можно инвертировать. То есть вывести только те строки, в которых нет указанных вхождений:
grep -v 'И' russian1
Для наглядности можно указать номера строк:
grep -vn 'И' russian1
Консольный вывод будет таким:
1:У лукоморья дуб зелёный
2:Златая цепь на дубе том
4:Всё ходит по цепи кругом
Как видно, в нем отсутствует третья строка — именно в ней и было указанное вхождение.
Можно использовать несколько регулярных выражений за один поиск. Для этого каждое выражение записывается после флага -e
:
grep -e 'ый$' -e 'це' ./*
Таким образом консольный вывод будет представлять собой последовательную комбинацию двух команд:
grep 'ый$' ./*
grep 'це' ./*
Для этого давайте перейдем на уровень выше — в корневой каталог:
cd
Теперь выполним рекурсивный поиск в корневом каталоге:
grep -r 'ый$' ./
Утилита grep
найдет вхождения в каталоге на уровень ниже — в папке с текстовыми файлами. Вывод будет следующим:
./files/russian1:У лукоморья дуб зелёный
./files/russian1:И днём и ночью кот учёный
Обратите внимание на адрес найденного файла — теперь он содержит название подкаталога.
Вернемся обратно в папку с файлами:
cd files
В некоторых случаях важно извлекать не только строку с найденными вхождениями, но и строки, окружающие ее. Например, для того, чтобы понимать контекст.
С помощью флага -A
можно указать количество строк для вывода ПОСЛЕ строки с найденным совпадением:
grep -A1 'ый$' ./*
Вывод будет таким:
./russian1:У лукоморья дуб зелёный
./russian1-Златая цепь на дубе том
./russian1:И днём и ночью кот учёный
./russian1-Всё ходит по цепи кругом
С помощью флага -B
можно указать количество строк для вывода ДО строки с найденным совпадением:
grep -B1 'ый$' ./*
Вывод будет таким:
./russian1-Златая цепь на дубе том
./russian1:И днём и ночью кот учёный
./russian1-Всё ходит по цепи кругом
С помощью флага -C
можно указать количество строк для вывода ДО и ПОСЛЕ строки с найденным совпадением:
grep -C1 'ый$' ./*
Вывод будет таким:
./russian1:У лукоморья дуб зелёный
./russian1-Златая цепь на дубе том
./russian1:И днём и ночью кот учёный
./russian1-Всё ходит по цепи кругом
Есть специальный флаг -c
, который вместо всех совпадений выводит только их количество:
grep -c 'ый$' ./*
Консольный вывод будет таким:
./code1:0
./english1:0
./russian1:2
Как видно, отсутствие совпадений тоже показывается в терминале. В данном случае есть только два вхождения в файле с текстом на русском языке.
Вывод можно обрезать до определенного количества строк с помощью флаг -m
. После флага сразу без пробела указывается количество строк:
grep -m1 'ый$' ./*
Таким образом в консоли будет не этот вывод:
./russian1:У лукоморья дуб зелёный
./russian1:И днём и ночью кот учёный
А более короткая его версия:
./russian1:У лукоморья дуб зелёный
Для поиска сразу в нескольких каталогах указывается регулярное выражение, содержащее возможный путь искомых файлов:
grep 'su' ./*
В терминале появится комбинированный вывод со строками из нескольких файлов:
./code1:const sum = number1 + number2;
./code1:console.log('Сумма чисел ' + number1 + ' и ' + number2 + ' равна ' + sum);
./english1:However little known the feelings or views of such a man may be on his first entering a neighbourhood, this truth is so well fixed in the minds of the surrounding families, that he is considered as the rightful property of some one or other of their daughters.
Можно заметить, что консольный вывод при поиске в директории отличается от консольного вывода при поиске в файле — теперь каждая найденная строка отмечается адресом файла, в котором она записана.
Во время поиска в каталогах можно включать и исключать файлы с помощью флагов include
и exclude
.
Например, можно убрать из предыдущего поиска файл с английским текстом:
grep --exclude 'english1' 'su' ./*
Теперь в терминале появится такое сообщение:
./code1:const sum = number1 + number2;
./code1:console.log('Сумма чисел ' + number1 + ' и ' + number2 + ' равна ' + sum);
Мы могли бы получить тот же самый вывод, включив в поиск только файл с кодом:
grep --include 'code1' 'su' ./*
Важно понимать, что название файла для исключения и включения — тоже регулярное выражение.
То есть можно сделать так:
grep --include '*s*1' ' ' ./*
Эта команда ищет знак пробела только в тех созданных файлах, в названии которых есть буква «s» и которые заканчиваются символом «1».
Помимо файлов, можно исключать и целые каталоги.
Давайте сперва поднимемся на уровень выше:
cd
Теперь выполним рекурсивный поиск в текущем каталоге, указывая папки для исключения с помощью опции exclude-dir
:
grep --exclude-dir='files' -R 'su' ./*
В этом случае папка с файлами для поиска будет исключена из консольного вывода.
Вернемся обратно в каталог с файлами:
cd files
Регулярные выражения для поиска вхождений можно вынести в отдельный файл, а его в свою очередь уже указывать в команде. Иногда это полезно, когда одни и те же регулярные выражения используются слишком.
Для этого создается файл с произвольным именем, внутри которого прописываются выражения:
sudo nano regulars
Каждое регулярное выражение пишется с новой строки:
su
ый$
После чего можно вызвать команду вместе с флагом -f
:
grep -f regulars ./*
Консольный вывод будет содержать все строки, в которых есть вхождения указанных выражений:
./code1:const sum = number1 + number2;
./code1:console.log('Сумма чисел ' + number1 + ' и ' + number2 + ' равна ' + sum);
./english1:However little known the feelings or views of such a man may be on his first entering a neighbourhood, this truth is so well fixed in the minds of the surrounding families, that he is considered as the rightful property of some one or other of their daughters.
./regulars:su
./russian1:У лукоморья дуб зелёный
./russian1:И днём и ночью кот учёный
Обратите внимание на эту строку консольного вывода:
./regulars:su
Так как файл с регулярными выражениями мы разместили в той же папке, где и файлы с текстами, и ее же указали в качестве источника поиска, утилита grep
нашла вхождение и в файле с регулярным выражением.
То есть утилита grep
в момент поиска не игнорирует файл, который выступает источником регулярных выражений для этого же самого поиска. Учитывайте это!
Исправить это можно с помощью исключения файла с регулярными выражениями:
grep -f regulars --exclude='regulars' ./*
Разверните свой Linux-сервер<br/>в Timeweb Cloud
В большинстве UNIX-подобных систем команда grep
реализует мощные возможности по поиску текстовой информации в файловой системе ОС.
Помимо этого, команда grep
неплохо адаптирована к конвейерам (pipeline) Linux, позволяя обрабатывать не только внешние файлы, но и выводы других консольных команд. Это достигается за счет использования регулярных выражений и конфигурации поиска различными флагами.
Комбинируя все функциональные возможности этой утилиты, можно решать самые разные задачи поиска. Можно сказать, что команда grep
— это «перочинный ножик» для поиска информации в операционных системах на базе Linux.