grep: примеры использования Печать
Добавил(а) microsin   

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

Например, команда

# grep gregor /etc/passwd

выдаёт строку

gregor:*:1001:1001:gregorlgn:/home/gregor:/bin/sh

что говорит о том, что командный интерпретатор для пользователя gregor - sh.

Строгий поиск. Пример строгого (опция w) поиска последовательности символов DEADBEEF по содержимому всех файлов в текущем каталоге и в его подкаталогах (опция r), с отображением номера строки, где встретилась эта последовательность (опция n). Строгий поиск означает, что будут выведены только те результаты, где указанная последовательность точно совпадает со словом, но не с частью слова:

$ grep -rnw DEADBEEF

Нестрогий поиск. Без опции w тот же пример выдаст результаты, где указанная последовательность совпадает как полностью со словом, так и с частью слова. Таким образом, будут выведены также результаты совпадений, где содержится, к примеру, слово 0xDEADBEEF:

$ grep -rn DEADBEEF

Опция l. Указать только имена файлов без результатов совпадения можно, если указать опцию l (маленькая L):

$ grep -rnwl DEADBEEF

Поиск в определенном каталоге и его подкаталогах. Следующий пример начнет поиск слова USB в файлах каталога /var/log и его подкаталогах:

$ grep -rnw USB /var/log

Поиск только в определенных файлах. С помощью опции --include="фильтр" можно ограничить поиск только определенными файлами. Например, вот так можно искать строку "sprintf" только в заголовочных файлах:

$ grep --include="*.h" -rnw sprintf

А как искать слова со спецсимволами? Предположим, нужно найти вхождение последовательности символов -lmpsse, для этого нужно применить двойные кавычки, и для символа '-' применить экранирование. Иначе символ дефиса будет принят как часть регулярного выражения.

$ grep -rnw "\-lmpsse"

[Совместное использование find и grep]

Например, следующая команда выводит список скриптов, в содержимом которых содержится слово test (поиск стартует рекурсивно с корневого каталога):

# find / -name "*.sh" | grep test

% ps -ax | grep inetd
  198  ??  IWs    0:00.00 inetd -wW

temp=`eval ifconfig $outside | grep -E -o --max-count=1 --regexp=$regex`

Здесь в переменную $temp записывается результат фильтрации вывода ifconfig. Опция -E включает использование регулярных выражений в шаблоне (grep -E синоним egrep), -o включает вывод не всей строки, а только то, что совпало с шаблоном, --regexp задает шаблон - регулярное выражение.

Следующая строка ищет все строки, в которых встречается слово cdp (locate cdp), но не встречается слово cdplay (grep -v cdplay):

# locate cdp | grep -v cdplay | more

Идея простая - grep ищет слова 25%, 50%, 75% и 100%, и выдает 52 строки перед совпадением:

# more pinglog.txt | grep -f ping_patterns.txt -B 52 > pinglog_filtered.txt

Теперь комментарии. Входной файл, как вы уже догадались pinglog.txt, выводит на вход grep команда more. Опция -f указывает grep брать паттерны для совпадения из файла ping_patterns.txt. Содержимое ping_patterns.txt (не забываем в конце этого файла указать возврат каретки):

25%
50%
75%
100%

Далее опция -B указывает включить в вывод grep еще 52 строки ПЕРЕД местом, где обнаружено совпадение с паттерном. Таким образом, в файл pinglog_filtered.txt попадет только то, что нам нужно.

tail -f /var/www/httpd-logs/mydomain.ru.access.log | grep -o http://.*.html | uniq

Результат:

http://microsin.net/adminstuff/hardware/s-pen-galaxy-note-inside.html
http://microsin.net/adminstuff/others/russia-post-sending.html
http://microsin.net/programming/AVR/avr077-opto-isolated-emulation-for-the-debugwire.html
http://microsin.net/adminstuff/windows/ux32vd-install-windows7-on-integrated-ssd.html
http://microsin.net/adminstuff/hardware/relay-and-transistor-as-electronic-switches.html
http://microsin.net/adminstuff/hardware/relay-and-transistor-as-electronic-switches.html
http://microsin.net/adminstuff/others/altium-designer-howto.html
http://microsin.net/programming/PC/c-sharp-faq.html
http://microsin.net/programming/AVR/atmega-ct1-pulse-counting.html
http://microsin.net/adminstuff/windows/move-windows-xp-to-new-hardware.html
http://microsin.net/programming/PC/dll-building-and-using.html
http://microsin.net/adminstuff/cisco/qos-setup-example.html

В этом примере опция -o для grep указывает выводить только части совпадения с шаблоном "http://.*.html", а команда uniq оставляет только уникальные (не повторяющиеся друг за другом) строки.

Вместо того, чтобы показать результат фильтрации, grep выдает:

$ tail -f ~/logfile.txt | grep ADC
W (6813) ADC SINGLE: 4.28V
W (6813) ADC SINGLE: 4.27V
W (6813) ADC SINGLE: 4.23V
Двоичный файл (стандартный ввод) совпадает

Проблема связана с тем, что на вход grep могли попасть символы с многобайтной кодировкой (например ESC-коды или UTF8). Для решения проблемы необходимо в командную строку grep добавить опцию -a:

$ tail -f ~/logfile.txt | grep -a ADC

Опция -a (и её синоним --text) указывает обрабатывать двоичный входной файл так же, как это был бы текстовый файл. Указание опции -a также эквивалентно указанию --binary-files=text в командной строке.

Это можно сделать с помощью опции --exclude-dir=имя_каталога. Пример, который ищет точное вхождение строки CMAKE_CXX_COMPILER_VERSION в файлах каталога ../.., исключая при этом папку ./build:

$ grep --exclude-dir=build -rnw CMAKE_CXX_COMPILER_VERSION ../..

Это можно сделать с помощью опции --exclude=какие_файлы_искать_не_надо. Пример, который ищет точное вхождение строки riscv64-unknown-elf в файлах каталога ../.., исключая при этом все файлы, оканчивающиеся на .a и .map:

$ grep --exclude="*.map" --exclude="*.a" -rnw "riscv64-unknown-elf" ../..

[Ссылки]

1. Мой переход с Windows на Ubuntu.
2. man grep site:man7.org.
3Команда tail для Windows.