Найти тему
Блокнот математика

grep: поиск по файлам

Хочу рассказать о чрезвычайно полезной утилите для поиска по файлам: если вы еще ею не пользуетесь (по незнанию), то это надо срочно исправить!

grep означает "Global Regular Expression and Print", то есть "Ищи везде по регулярному выражению и выдай результат". Это консольная утилита для поиска в файле или файлах. Создана была в 1974 году! То есть скоро отпразднует солидный юбилей: компьютерные сущности редко столько живут, это и людям не всем удается.

Зачем нужна?

Например, не помните, в каком модуле лежит процедурка для расчета силы Кориолиса в данных координатах? Или в каких файлах отрабатывается матьих граница между морями? Или используется переменная IceSalinity чтоб ее черти взяли? Куда записал рецепт сборки библиотеки, там еще была переменная окружения WTF? В какой ешкин кот главе диссертации доказывалась теорема о сходимости с меточкой my_thm_converg? И почему тех ругается, что формул с меткой hz более одной? Точно была одна, откуда еще?? И как я ее найду в сорока двух файлах??! А сколько раз я ссылаюсь на Перегвоздичихина, и где? А вот в 4Гб-ном файле выдачи где-то должно быть сообщение, что лед полностью растаял — Вим его найдет, но загружать Вим таким файлом было бы негуманно — справится, но не мгновенно.

Вот тут греп тут как тут. Я не представляю себе работы без него, равно как без Вима и Перла.

Есть и в самом Перле оператор grep, который просеивает массив или список через блок кода (в простом случае регулярку) и оставляет те, на которых результат "истина" (а ложны в Перле только число 0, пустая строка и неопределенное значение, все остальное истина.
Например, вот так можно просеять список, оставив одни натуральные числа:
grep {/\d\+/} @list;

Но мы про консольную утилиту grep. Консольный grep принимает выражение (если есть пробелы и спецсимволы, лучше в кавычках) и файлы, и проверяет строки на соответствие. Например:

grep 666 *.txt
grep '^\s*if(b<0)' *.f90

Если файл не указан или указан -, то поиск ведется в STDIN. Это удобно для перенаправлений:

pdflatex dissert.tex | grep undefined

Еще есть ключи. Их много, и я все описывать не буду. Однако:

-i включает регистронезависимый поиск. Вот это полезно! Например,

grep -i 'relativity' *.tex

-v инвертирует поиск, так что выводятся строки, которые не удовлетворяют выражению.

Очень полезный ключ -P включает регулярные выражения Перл. Там очень много возможностей, которые, может, не все поддерживаются, не те задачи. Но удобно, чтобы не путаться в диалектах:

grep -iP '\b\wice\d+\b' *.f90 вместо grep -i '\<\wice[0-9]\+\>' *.f90

К тому же, регулярки Перла помощнее будут!

-c предписывает не выводить строки, а только посчитать их количество.

А -n выводит номера строк, помимо них самих.

-o позволяет вывести только совпадения, а не строки целиком.

-H и -h включают и выключают вывод имени файла с совпадением. По умолчанию, если файлов более одного, имена выводятся, а если нет, то нет. Разумно... но если надо поменять поведение, например, передать найденное дальше, то вот.

-A число и -B число выводит контекст: заданное число строк после/до найденной. А можно с помощью -C число вывести контекст с двух сторон. Совпадения разделяются строкой с -- (два минуса).

Можно не искать в файлах с заданным шаблоном: --exclude=шаблон

Ключи -r и -R позволяют включить рекурсивный поиск в подкаталогах; разница в том, что -r не проходит по символьным ссылкам, а -R проходит. Очень полезно для поиска в проектах, где код разнесен по разным каталогам! Отследить, какая функция где вызывается и какая переменная где нужна. Меня просто спасало, когда я работал с чужими проектами, а приходилось. Удачи в поисках!

Путеводитель по каналу