- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF133:Grep
Материал из Linuxformat.
Содержание |
grep Супер-поиск по команде
- Любите командную строку и хотите достичь большего? Исследуйте grep с Фэй ‘Шерлок’ Уильямс – и отныне ничего уже не потеряете.
Команда grep – мощнейшее средство поиска в файлах. Как и со многими утилитами командной строки, освоившись в ней, вы обнаружите, что она удивительно быстра и точна. Однако многие пользователи Linux снисходят до изучения не более одной-двух опций grep, после чего применяют их как способ поиска «за все». А ведь чуток времени, потраченного на изучение возможностей grep, окупится сторицей – и нет ничего приятнее, чем точное знание, как по команде мгновенно получить нужный результат. Мы начнем с основ и наработаем багаж вариантов использования grep, а завершим все кое-какими уловками – чтобы проверить, алчете ли вы еще.
На рисунке приведен пример поиска в файле календаря OpenBSD. Такие установлены по умолчанию в Ubuntu, Mint и многих других дистрибутивах, и даже на Mac. А если у вас (как и у меня) Fedora, и вы не желаете оставаться в стороне, добавьте их вручную, выбрав в своем рабочем столе опцию Система > Администрирование > Добавить/Удалить приложение. Найдите calendar, установите флажок рядом с Утилитой напоминания и нажмите Применить. Или просто выполните yum install calendar в командной строке. А теперь о главном.
Простой поиск
Команда grep распознает следующее:
- Любые опции фильтрации результатов поиска.
- Строку (или шаблон) искомого.
- Место осуществления поиска – файл или каталог.
Для примера тут же опробуйте:
grep first /usr/share/calendar/calendar.history
Обсудим полученное. Мы попросили grep найти все вхождения строки ‘first’ в файле calendar.history. Помните, что grep чувствительна к регистру – попробуйте выполнить grep First /usr/share/calendar/calendar.history и сравните то, что получится в результате.
Если вы хотите осуществить поиск без учета заглавных и строчных букв, добавьте опцию -i для игнорирования регистра.
grep -i first /usr/share/calendar/calendar.history
Пока все хорошо. А вдруг необходимо выполнить поиск в нескольких файлах? Календарей, которые вы захотите просмотреть, немало, так что смените путь к файлу на каталог и добавьте опцию -r, чтобы поиск grep осуществлялся рекурсивно по всем файлам и подкаталогам, находящимся в указанном каталоге:
grep -ir first /usr/share/calendar
Каждая строка вывода теперь предваряется именем файла. Заметим, что порядок добавления опций после символа ‘-’ роли не играет.
Иногда примеры, приведенные выше, вас спасают; если вы ищете письмо, которое написали некому Дону Дженкинсу, и знаете, что оно где-то в домашнем каталоге, вы, вероятно, найдете файл при помощи:
grep -r Jenkins /home/faye
Но что если вы запустили команду grep и не получили ожидаемого результата, или получили столько совпадений, что не можете отличить одну строку от другой?
Настраиваем вывод
Давайте упростим восприятие того, что мы делаем, включив опцию подсветки в grep. На сей раз поищем ‘war’.
grep -ri --color=auto war /usr/share/calendar/
Добавьте строку alias grep=’grep --color=auto’ в файл .bashrc, расположенный в домашнем каталоге, и подцветка включится уже навсегда.
Уже лучше! И теперь можно увидеть искомую строку (если у вас Linux Mint, подцветка включена по умолчанию). Далее, избавимся от всех подстрок, поскольку grep выводит все совпадения, даже если они являются частью других слов. Например, наш поиск war также прихватит строку с "Rod Stewart". Этого можно избежать, запросив поиск только полных слов при помощи опции -w – количество совпадений уменьшится на две трети. Об этом мы узнали, заставив grep подсчитать количество вхождений, вместо их прямого вывода, по опции -c:
grep -riwc war /usr/share/calendar
Видно, что grep выводит количество совпадений для всех файлов, в которых осуществлялся поиск. Если вы искали в единственном файле, вернется одно число.
Прежде чем двинуться дальше, еще кое-что. Отыскивая более одного слова, следует пользоваться одиночными кавычками для учета пробелов:
grep -ri ‘civil war’ /usr/share/calendar
Все это хорошо, но вот поиск чего-то вроде “$20” дает нечто ужасно неверное. Что случилось?
ОК, вам следует знать о grep еще кое-что, и это тот факт, что он разрабатывался для работы с шаблонами или регулярными выражениями. Это обширная тема, но вот вам ее вершки (см. примеры внизу или же загляните в LXF80, если хотите узнать больше). Символы вроде $*.?+ имеют свои особые значения и позволяют искать в файлах сложные и точные шаблоны. Если вы ищете строку, содержащую эти спецсимволы, предварите их обратным слэшем:
grep -ri ‘\$20’ /home/faye/statement.txt
Иначе grep интерпретирует символ не просто как литерал, и результат может содержать то, что вы хотели получить, а может, и нет.
Наконец, при желании сохранить результаты поиска можно перенаправить вывод grep в файл, следующим образом:
grep -riw first /usr/share/calendar > /home/faye/search.txt
Будьте осторожны, поскольку, сохранив файл в том же каталоге (или подкаталоге), где осуществлялся рекурсивный поиск, вы можете угодить в бесконечный цикл: grep примется выдавать вывод о создаваемых самим же файлах. Если вы случайно это сделали, просто нажмите Ctrl+C для выхода из цикла и удалите файл результата, поскольку он явно будет массивным.
Став завзятым линуксоидом, вы обнаружите, что grep незаменим, но если вы действительно желаете освоить эту команду, следует предпринять несколько дополнительных шагов. Во-первых, попользуйтесь man-страницей (по завершении чтения нажмите Q):
man grep
Так вы получите детальное описание опций grep. Стоит также попробовать команду help:
grep --help
Она превосходна для быстрого напоминания. Она сообщит, как вставить в вывод номера строк (великолепно для файлов с исходными кодами), отобразить только имена файлов, вывести контекст над и под найденными строками или даже все, что не соответствует искомому.
Во-вторых, если вы сумеете отвести немного времени на изучение использования регулярных выражений, то результат окупится вдесятеро – тогда-то мир grep действительно перед вами раскроется.
Почему grep?
Слово ‘grep’ – сокращение по первым буквам стандартной серии команд, используемых в ed, одном из однострочных текстовых редакторов Unix. Команды global/regular expression/print велят ed помечать каждую входную строку, соответствующую регулярному выражению (или шаблону поиска), и выводить ее на экран. Это применялось так часто, что grep в Unix вынесли в отдельную утилиту. Ее история насчитывает три десятилетия и несколько различных версий и алгоритмов, и она все так же популярна, как и при рождении.
Четыре ценных шаблона
- Найти все строки, содержащие слово ‘first’ и ‘1954’, в этом порядке: grep -ri first.*1954 /usr/share/calendar
- Найти IP-адрес. Здесь надо много вводить, и точность будет не 100%, поскольку результат включит, скажем, 9.9.9.9999, а это, конечно, адрес неверный. Можно написать более строгий запрос, но снижение количества ложных срабатываний не стоит увеличения сложности выражения. grep -r ‘\(digit:\+\.\)\{3\}digit:\+’ /etc/sysconfig/networkscripts
- Найти URL (вместо \.com подставьте \.ru, и т. д.). Мы указали обычный домен длиной от 3 до 50 символов. grep -r ‘www\..\{3,50\}\.com’ /home/faye/.mozilla/
- Наконец, вот две команды grep, связанные вместе через перенаправление вывода. В результате выводится общее число совпадений во всех файлах сразу, а не в каждом по отдельности: grep -riwh first /usr/share/calendar | grep -ic first