Команда grep – полезные ключи и примеры использования

У команды "grep" довольно много различных особенностей. особенно, если учесть, что с английского это "решето" – а что может войти в решето , не факт что выйдет!

Опубликовано: 21.11.2019

Поиск слова в файле с помощью grep

Пожалуй, самый простой пример использования команды grep – это поиск подстроки в файле:

grep "Безухов" voyna-i-mir-tom-1.txt

– выведет строки, в которых grep нашёл точное совпадение. Однако, в этом списке строк сложно ориентироваться. Предлагаю немного апгрейдить нашу команду, чтобы и номера строк выводила, да ещё и контекст добавляла:

grep -in -C 3 "Безухов" voyna-i-mir-tom-1.txt

Пробежимся по ключам:

В итоге мы получим нечто следующее:

--
848-
849-Но дамы невольно смеялись и сами.
850-
851:— Насилу спасли этого несчастного, — продолжала гостья. — И это сын графа Кирилла Владимировича Безухова так умно забавляется! — прибавила она. — А говорили, что так хорошо воспитан и умен. Вот всё воспитание заграничное куда довело. Надеюсь, что здесь его никто не примет, несмотря на его богатство. Мне хотели его представить. Я решительно отказалась: у меня дочери.
852-
853-— Отчего вы говорите, что этот молодой человек так богат? — спросила графиня, нагибаясь от девиц, которые тотчас же сделали вид, что не слушают. — Ведь у него только незаконные дети. Кажется… и Пьер незаконный.
854-
--

Рекурсивный поиск текста в директории с grep

Искать в файле – это хорошо, но что делать, если ты не помнишь, в каком файле было то, что тебе нужно. К примеру, программируя на Си под MacOS я часто не могу понять, куда положили чудесные функции из сторонних библиотек. Тогда мне надо найти в директории /usr/local/include файл для подключения, имея только название функции:

$ grep -rl SDL_GetError /usr/local/include
/usr/local/include/SDL/SDL_error.h
/usr/local/include/SDL/SDL_ttf.h
/usr/local/include/SDL/SDL_mixer.h
/usr/local/include/SDL/SDL_image.h
/usr/local/include/SDL2/SDL_error.h
/usr/local/include/SDL2/SDL_main.h
/usr/local/include/SDL2/SDL_ttf.h
/usr/local/include/SDL2/SDL_mixer.h
/usr/local/include/SDL2/SDL_image.h

– значит SDL_GetError использовалась в перечисленных файлах – уже проще. Более того, по названию файлов я догадаюсь, что функция таки описана в /usr/local/include/SDL/SDL_error.h... Просто так привык. Давайте расскажу, что означают эти флаги, после расскажу, как поискать уже привычным нам образом: с выводом строк + контекстом, например, в 3 строки сверху и снизу. Кстати, вы уже можете задуматься сами – какие ключи/флаги надо установить grep. Итак,

Если же мы хотим спокойно и комфортно просмотреть все найденные вхождения, то нам скорее подойдёт:

$ grep -rin -C 3 SDL_GetError /usr/local/include
/usr/local/include/SDL/SDL_error.h-41- */
/usr/local/include/SDL/SDL_error.h-42-/*@{*/
/usr/local/include/SDL/SDL_error.h-43-extern DECLSPEC void SDLCALL SDL_SetError(const char *fmt, ...);
/usr/local/include/SDL/SDL_error.h:44:extern DECLSPEC char * SDLCALL SDL_GetError(void);
/usr/local/include/SDL/SDL_error.h-45-extern DECLSPEC void SDLCALL SDL_ClearError(void);
/usr/local/include/SDL/SDL_error.h-46-/*@}*/
/usr/local/include/SDL/SDL_error.h-47-
--
...

– все использованные флаги/ключи нам уже изветны. Если вам неочевидно, что тут происходит, перечитайте заметку выше.

Поиск по регулярному выражению в grep

Это всё, конечно, замечательно, но я бы хотел при поиске определения функции искать именно определение функции, без указания файлов, где она только упоминается. То есть мне нужна строка, где будет тип возвращаемого значения (char*), после которого будет идти какое-то количество спец-слов и пробелов, а потом название функции. Нет ничего проще:

grep -r -C 3 -E 'char.*?\*.*?SDL_GetError' /usr/local/include

Почти все ключи нам известны кроме -E – он включает режим расширенных регулярных выражений для шаблона поиска. Так в данном регулярном выраженнии мы написали 'char.?*.?SDL_GetError' то есть:

Схематично это можно выразить следующим образом:

                | char | .*? | \* |  .*?    | SDL_GetError |
extern DECLSPEC | char |     | *  | SDLCALL | SDL_GetError | (void);

Регулярные выражения – отнюдь не очевидная тема. И понять её с ходу вы вряд лм сможете. Я подготовил некоторое объяснение в рамках второй пары по Linux. Но явно нужно более тщательное рассмотрение этой темы.

Также может быть вам интересно:
ПрограммыFreeBSDТерминал/КонсольUbuntu LinuxLinuxТрюки BashНастройки
← Как создать неизменяемый файл в Linux / MacOS / FreeBSD Как найти самые большие папки и файлы в Linux →