Як використовувати команду grep в Linux

Команда `grep` у Linux – це потужний інструмент для пошуку текстових рядків та шаблонів у файлах. Вона дозволяє знаходити відповідні рядки серед великої кількості даних, а також працює з виводом інших команд через конвеєр. Розглянемо детальніше, як саме використовувати цю утиліту.

Історія виникнення grep

Команда `grep` завоювала популярність у світі Linux і Unix завдяки кільком факторам. По-перше, вона відрізняється високою корисністю. По-друге, її можливості настільки широкі, що можуть вразити навіть досвідчених користувачів. І, по-третє, її створили протягом однієї ночі для вирішення конкретного завдання. Перші два пункти є очевидними, а третій – дещо несподіваним.

Кен Томпсон, витягнувши функціонал пошуку за регулярними виразами з редактора `ed` (вимовляється “і-ді”), створив невелику програму для персонального використання з метою пошуку в текстових файлах. Його керівник у Bell Labs, Дуг Макілрой, звернувся до Томпсона, описавши проблему, з якою зіткнувся один з їхніх колег, Лі Макмехон.

Макмехон проводив текстовий аналіз для ідентифікації авторів “Федералістських документів”. Йому потрібен був інструмент, який би дозволяв шукати фрази та рядки в текстових файлах. Того ж вечора Томпсон протягом приблизно години перетворив свій особистий інструмент на загальнодоступну утиліту, яку назвав `grep`. Назва походить від командного рядка редактора `ed` – `g/re/p`, що означає “глобальний пошук за регулярними виразами”.

Ви можете знайти відео, де Томпсон розповідає про народження `grep` Браяну Кернігану.

Простий пошук за допомогою grep

Для пошуку конкретного рядка у файлі, введіть у командному рядку пошуковий термін і назву файлу:

Відобразяться рядки, що містять вказаний термін. У наведеному прикладі це лише один рядок. Знайдений текст буде виділено, оскільки в більшості дистрибутивів Linux для `grep` встановлено псевдонім:

alias grep='grep --colour=auto'

Розглянемо випадок, коли збігається кілька рядків. Шукаємо слово “Середнє” у файлі журналу програми. Оскільки ми не знаємо, чи записане слово з великої чи малої літери, використаємо параметр `-i` (ігнорувати регістр):

grep -i Average geek-1.log

Буде виведено кожен рядок, який містить слово “середнє” у будь-якому регістрі, і відповідний текст буде підсвічено.

Для виведення рядків, які *не* містять заданого терміну, використовуйте параметр `-v` (інвертувати збіг):

grep -v Mem geek-1.log

Текст не буде виділено, оскільки відображаються лише рядки, що не відповідають пошуковому запиту.

Можна зробити так, щоб `grep` працював у безшумному режимі. Результат його роботи повертається в оболонку як значення. Нульовий результат означає, що рядок знайдено, одиничний – що не знайдено. Код повернення можна перевірити за допомогою спеціального параметра `$?`:

grep -q average geek-1.log
echo $?
grep -q wdzwdz geek-1.log
echo $?

Рекурсивний пошук за допомогою grep

Для пошуку у вкладених папках використовуйте параметр `-r` (рекурсивний). Зауважте, що потрібно вказати шлях, а не ім’я файлу. Наприклад, шукаємо у поточному каталозі “.” та у всіх його підпапках:

grep -r -i memfree .

Вивід міститиме назви папок та файлів для кожного знайденого рядка.

`grep` може переходити за символічними посиланнями, якщо використовувати параметр `-R` (рекурсивне розіменування). У цьому прикладі є символічне посилання `logs-folder`, яке вказує на `/home/dave/logs`.

ls -l logs-folder

Повторимо попередній пошук, але з параметром `-R`:

grep -R -i memfree .

Тепер пошук буде проведено також і в каталозі, на який вказує символічне посилання.

Пошук цілих слів

За замовчуванням `grep` знаходить рядки, які містять пошуковий термін будь-де, навіть всередині іншого слова. Розглянемо приклад: пошук слова “free”.

grep -i free geek-1.log

У результатах є рядки, що містять “free”, але це не окремі слова, а частина слова “MemFree”.

Щоб `grep` шукав тільки окремі слова, використовуйте параметр `-w` (регулярний вираз слова).

grep -w -i free geek-1.log
echo $?

Цього разу результатів немає, оскільки окреме слово “free” не зустрічається у файлі.

Використання кількох пошукових термінів

Параметр `-E` (розширений регулярний вираз) дозволяє шукати декілька слів. Цей параметр є аналогом застарілої команди `egrep`.

Наступна команда шукає два слова: “середній” та “вільна пам’ять”.

grep -E -w -i "average|memfree" geek-1.log

Виводяться рядки, що містять будь-який з цих термінів.

Можна шукати як окремі слова, так і фрагменти слів.

Параметр `-e` дозволяє використовувати кілька пошукових термінів у командному рядку. Також можна використовувати дужки регулярних виразів, наприклад `[]`, щоб створити шаблон. У цьому випадку `grep` буде шукати рядки, що містять `kB` або `KB`.

Знайдено обидва рядки, причому деякі містять обидва варіанти.

Точно відповідні лінії

`-x` (рядковий регулярний вираз) знаходить рядки, де *весь* рядок збігається з пошуковим терміном. Наприклад, пошукаємо мітку дати та часу, яка, як відомо, зустрічається лише один раз:

grep -x "20-Jan--06 15:24:35" geek-1.log

Знайдено та виведено один відповідний рядок.

Можна виводити лише рядки, які *не* збігаються. Це зручно, коли переглядаєте файли конфігурації, де коментарі часто ускладнюють пошук потрібних налаштувань. Ось приклад з файлом `/etc/sudoers`:

За допомогою наступної команди ми виключимо рядки коментарів:

sudo grep -v "https://www.wdzwdz.com/496056/how-to-use-the-grep-command-on-linux/#" /etc/sudoers

Результат значно зручніший для аналізу.

Відображення лише відповідного тексту

Іноді потрібно виводити не весь рядок, а лише сам текст, який відповідає пошуковому терміну. Для цього використовується параметр `-o` (тільки відповідний).

grep -o MemFree geek-1.log

Виводиться лише текст, який відповідає заданому терміну.

Підрахунок за допомогою grep

`grep` також надає числову інформацію. За допомогою параметра `-c` можна підрахувати, скільки разів термін з’являється у файлі:

grep -c average geek-1.log

`grep` повідомляє, що термін “average” зустрічається у файлі 240 разів.

Щоб вивести номер рядка для кожного збігу, використовуйте параметр `-n`.

grep -n Jan geek-1.log

Номер рядка відображається на початку кожного відповідного рядка.

Для обмеження кількості виведених результатів використовуйте параметр `-m` (максимальна кількість). Наприклад, виведемо лише перші 5 рядків:

grep -m5 -n Jan geek-1.log

Додавання контексту

Часто корисно бачити додаткові (можливо, невідповідні) рядки для кожного збігу. Це допомагає зрозуміти, які рядки є найбільш цікавими.

Для виведення рядків *після* збігу використовуйте параметр `-A` (після контексту). Наприклад, виведемо 3 рядки після відповідного:

grep -A 3 -x "20-Jan-06 15:24:35" geek-1.log

Щоб вивести рядки *перед* збігом, використовуйте параметр `-B` (контекст перед).

grep -B 3 -x "20-Jan-06 15:24:35" geek-1.log

Для виведення рядків *до і після* збігу використовуйте параметр `-C` (контекст).

grep -C 3 -x "20-Jan-06 15:24:35" geek-1.log

Відображення відповідних файлів

Щоб побачити назви файлів, що містять пошуковий термін, використовуйте параметр `-l` (файли зі збігом). Наприклад, дізнаємося, які C-файли містять посилання на заголовок `sl.h`:

grep -l "sl.h" *.c

Виводяться лише назви файлів, а не самі відповідні рядки.

Аналогічно, можна шукати файли, які *не* містять заданий термін, за допомогою параметра `-L` (файли без відповідності).

grep -L "sl.h" *.c

Початок і кінець рядків

`grep` може знаходити збіги лише на початку або в кінці рядка. Символ `^` відповідає початку рядка. Знайдемо рядки, що починаються з пробілу:

grep "^ " geek-1.log

Відобразяться рядки, що починаються з пробілу.

Для відповідності кінцю рядка використовуйте символ `$`. Знайдемо рядки, що закінчуються на “00”:

grep "00$" geek-1.log

Виводяться рядки, що закінчуються на “00”.

Використання Pipes з grep

`grep` можна використовувати у конвеєрах з іншими командами, перенаправляючи її вихід та вхід.

Наприклад, щоб побачити усі згадки рядка “ExtractParameters” у вихідних C-файлах, але у меншому обсязі, можна скористатися командою:

grep "ExtractParameters" *.c | less

Результат буде виведений за допомогою утиліти `less`.

Це дозволить переглядати список файлів та використовувати можливості пошуку `less`.

Якщо перенаправити вивід `grep` до `wc` і використати параметр `-l`, то можна підрахувати кількість рядків у вихідних файлах, що містять “ExtractParameters”. Хоча це можна зробити і за допомогою `grep -c`, це гарний спосіб продемонструвати роботу конвеєра:

grep "ExtractParameters" *.c | wc -l

Наступна команда перенаправляє вихід `ls` до `grep`, а потім до `sort`. Вона виводить файли у поточному каталозі, відбираючи ті, що містять “Aug”, і сортує їх за розміром:

ls -l | grep "Aug" | sort +4n

Розглянемо цю команду детальніше:

  • `ls -l`: Виводить довгий список файлів у поточному каталозі.
  • `grep “Aug”`: З цього списку відбирає рядки, що містять “Aug”. Зверніть увагу, що це також знайде файли, які мають “Aug” у своїй назві.
  • `sort +4n`: Сортує вивід `grep` по четвертому стовпчику (розмір файлу).

Таким чином, виводиться список файлів, змінених у серпні (незалежно від року), відсортований за розміром.

grep: Більше, ніж команда, ваш надійний союзник

`grep` – це чудовий інструмент, який має бути в арсеналі кожного користувача Linux. Існує з 1974 року, і досі актуальний завдяки своїй ефективності та корисності.

Поєднання `grep` з можливостями регулярних виразів відкриває ще більші горизонти для пошуку та аналізу даних.