Як використовувати команду `grep` для пошуку інформації у файлах
Команда grep — скорочення від Global Regular Expression Print — це утиліта Unix/Linux, яка сканує один або кілька файлів рядок за рядком і виводить кожен рядок, що відповідає заданому шаблону. Вона є стандартом де-факто для пошуку тексту в будь-якій POSIX-сумісній системі та підтримує як базові, так і розширені регулярні вирази, що дозволяє знаходити збіги від простого рядка до складних багатосимвольних шаблонів.
Якщо вам потрібна найкоротша відповідь: виконайте grep "pattern" filename для пошуку у файлі, додайте -r для рекурсивного пошуку в дереві каталогів, -i для пошуку без урахування регістру та -n для відображення номерів рядків поряд із результатами. Наведені нижче розділи охоплюють значно більше: реальні робочі процеси, проблеми з продуктивністю та розширені техніки регулярних виразів, які більшість посібників повністю оминають.
Що насправді робить grep під капотом
grep читає вхідні дані рядок за рядком і застосовує до кожного рядка скінченний автомат, похідний від вашого регулярного виразу. Реалізація GNU (стандартна в Linux) використовує алгоритм Boyer-Moore-Horspool для літеральних рядків і конструкцію Thompson NFA для шаблонів регулярних виразів. Саме ця архітектура пояснює, чому grep надзвичайно швидко працює з великими файлами — він уникає зворотного відстеження, на відміну від інструментів на основі PCRE, таких як perl або python.
У сімействі GNU coreutils існують три окремі бінарні файли:
| Команда | Рушій | Варіант використання |
|---|---|---|
grep | BRE / ERE (з -E) | Пошук збігів рядків загального призначення |
egrep | ERE (розширені регулярні вирази) | Скорочення для grep -E |
fgrep | Лише фіксовані рядки | Найшвидший; без інтерпретації регулярних виразів |
zgrep | BRE / ERE для стиснутих файлів | Архіви .gz, .bz2 |
pgrep | Пошук збігів імен процесів | Шукає в таблиці процесів, а не у файлах |
egrep та fgrep є застарілими псевдонімами в сучасних системах; у скриптах для забезпечення переносимості надавайте перевагу grep -E та grep -F відповідно.
Базовий синтаксис
grep [options] pattern [file ...]- pattern — рядок або регулярний вираз, взятий у лапки
- file — один або кілька шляхів до файлів; пропустіть для читання зі стандартного введення
- options — прапорці, що змінюють поведінку пошуку збігів, формат виведення або продуктивність
Мінімальний приклад, що знаходить кожен рядок зі словом "error" у syslog:
grep "error" /var/log/syslogЗавжди беріть шаблон у лапки. Шаблони без лапок, що містять метасимволи оболонки (*, ?, [, $), будуть розгорнуті оболонкою до того, як grep їх побачить, що призведе до мовчазних некоректних результатів.
Основні параметри, які повинен знати кожен адміністратор
Пошук у кількох файлах і каталогах
Перелічіть файли явно або використовуйте глобінг оболонки:
grep "error" access.log error.log debug.log
grep "error" *.logДля пошуку в усьому дереві каталогів використовуйте -r (слідкуйте за символічними посиланнями за допомогою -R):
grep -r "error" /var/log/Застереження: На виробничих серверах із глибоко вкладеними ієрархіями журналів необмежений -r може споживати значний обсяг вводу/виводу. Обмежте область пошуку за допомогою --include, щоб уникнути сканування бінарних файлів або нерелевантних розширень:
grep -r --include="*.log" "error" /var/log/Пошук без урахування регістру (-i)
grep -i "error" application.logЦе знаходить збіги для error, Error, ERROR, eRrOr та будь-якої іншої комбінації регістрів. Внутрішньо GNU grep з -i перетворює і шаблон, і вхідні дані на нижній регістр перед порівнянням, що додає невеликі накладні витрати на дуже великих файлах.
Відображення номерів рядків (-n)
grep -n "error" application.logПриклад виведення:
25:error occurred during processing
103:error: connection refusedНомери рядків незамінні, коли потрібно перейти безпосередньо до збігу в редакторі: vim +25 application.log відкриває файл на рядку 25.
Підрахунок збігів (-c)
grep -c "error" application.logПовертає лише кількість рядків зі збігами, а не самі рядки. При пошуку в кількох файлах кожен файл отримує власний лічильник:
grep -c "error" *.logaccess.log:0
debug.log:14
error.log:3Інвертований пошук (-v)
grep -v "error" application.logПовертає кожен рядок, який не відповідає шаблону. Практичне застосування: видалення рядків коментарів із файлу конфігурації перед передачею його далі по конвеєру:
grep -v "^#" /etc/nginx/nginx.conf | grep -v "^$"Це видаляє як рядки коментарів (що починаються з #), так і порожні рядки, залишаючи лише активні директиви.
Пошук цілих слів (-w)
grep -w "error" application.logБез -w пошук error також знаходив би збіги для errors, error_code та myerror. Прапорець -w прив’язує збіг до меж слів, визначених як переходи між символами слів ([a-zA-Z0-9_]) і символами, що не є символами слів.
Обмеження кількості рядків виведення (-m)
grep -m 5 "error" application.loggrep припиняє читання файлу після знаходження 5 рядків зі збігами. У файлі журналу розміром 10 ГБ, де потрібно лише підтвердити наявність шаблону, -m 1 може скоротити час виконання з секунд до мілісекунд, оскільки grep завершує роботу одразу після першого збігу.
Рядки контексту (-A, -B, -C)
Одна з найменш використовуваних функцій. При діагностиці помилки навколишні рядки часто містять першопричину:
grep -A 3 "error" application.log # 3 lines After the match
grep -B 3 "error" application.log # 3 lines Before the match
grep -C 3 "error" application.log # 3 lines of Context (before and after)Це різниця між тим, щоб побачити error: connection refused і побачити повний стек викликів або попередній запит, що спричинив помилку.
Підсвічування кольором (--color)
grep --color=auto "error" application.logБільшість дистрибутивів встановлюють alias grep='grep --color=auto' у /etc/profile.d/ або ~/.bashrc. Використовуйте --color=always при передачі в less -R для збереження ANSI-кодів:
grep --color=always "error" application.log | less -RВиведення лише частини рядка, що збігається (-o)
За замовчуванням grep виводить весь рядок зі збігом. Прапорець -o виводить лише ту частину рядка, яка відповідає шаблону:
grep -o "192.[0-9]*.[0-9]*.[0-9]*" access.logЦе витягує кожну IPv4-адресу з журналу доступу — по одній адресі на рядок виведення — що ідеально підходить для передачі в sort | uniq -c | sort -rn для пошуку найактивніших клієнтів.
Придушення виведення імені файлу (-h) та його примусове відображення (-H)
При пошуку в кількох файлах grep додає ім’я файлу перед кожним збігом. -h придушує це; -H примусово відображає навіть при пошуку в одному файлі. Використовуйте -H у скриптах для гарантованого однакового формату виведення незалежно від кількості переданих файлів.
Виведення лише імен файлів (-l та -L)
grep -l "error" *.log # files that contain the pattern
grep -L "error" *.log # files that do NOT contain the patternКорисно в скриптах розгортання для визначення файлів конфігурації, що посилаються на застарілий параметр.
Регулярні вирази з grep
Базові регулярні вирази (BRE)
grep за замовчуванням використовує BRE. Ключові метасимволи:
| Метасимвол | Значення | Приклад |
|---|---|---|
^ | Початок рядка | grep "^error" — рядки, що починаються з "error" |
$ | Кінець рядка | grep "error$" — рядки, що закінчуються на "error" |
. | Будь-який одиночний символ | grep "err.r" — збігається з "error", "errar" тощо |
* | Нуль або більше попередніх | grep "err*" — "er", "err", "errr" тощо |
[abc] | Клас символів | grep "[aeiou]" — будь-яка голосна |
[^abc] | Заперечений клас | grep "[^0-9]" — будь-який нецифровий символ |
| Екранування метасимволу | grep "." — літеральна крапка |
У BRE символи +, ?, {, }, (, ) та | повинні бути екрановані зворотною косою рискою, щоб сприйматися як метасимволи. Це є поширеним джерелом плутанини при переключенні між BRE та ERE.
Розширені регулярні вирази (ERE) з -E
grep -E "error|failure|critical" application.logERE робить синтаксис чистішим — +, ?, |, () та {} працюють без зворотних косих рисок:
grep -E "err(or|ata)?" application.log # matches "err", "error", "errata"
grep -E "[0-9]{1,3}.[0-9]{1,3}" access.log # partial IP pattern
grep -E "^(ERROR|WARN|FATAL)" app.log # lines starting with severity levelsPerl-сумісні регулярні вирази (PCRE) з -P
GNU grep підтримує PCRE через прапорець -P, що відкриває доступ до випереджальних та ретроспективних перевірок і нежадібних квантифікаторів:
grep -P "(?<=user=)w+" auth.log # extract username after "user="
grep -P "d{4}-d{2}-d{2}" app.log # ISO date formatВажливо: -P є розширенням GNU і недоступний у BSD grep (стандартний на macOS). Скрипти, що використовують -P, не є переносимими без встановлення GNU grep (brew install grep на macOS).
Пошук у стиснутих файлах за допомогою zgrep
Ротація журналів зазвичай стискає старіші журнали за допомогою gzip. zgrep дозволяє шукати в них без ручного розпакування:
zgrep "error" /var/log/syslog.2.gzДля файлів .bz2 використовуйте bzgrep. Для файлів .xz використовуйте xzgrep. Якщо потрібно шукати одночасно в стиснутих і нестиснутих журналах однією командою:
zgrep -r "error" /var/log/Крайній випадок: zgrep внутрішньо викликає zcat для розпакування, а потім передає дані в grep. Він не підтримує всі прапорці grep. Якщо вам потрібні -P або -o для стиснутих файлів, спочатку розпакуйте їх у тимчасовий файл або використовуйте zcat file.gz | grep -P "pattern".
Поєднання grep з іншими командами
Справжня потужність grep проявляється при його поєднанні з іншими утилітами через конвеєри.
Фільтрація виведення процесів
ps aux | grep "[n]ginx"Трюк із дужками [n]ginx запобігає появі самого процесу grep в результатах, оскільки шаблон [n]ginx не збігається з літеральним рядком [n]ginx у списку процесів.
Витягування та агрегування даних журналів
grep "error" application.log | sort | uniq -c | sort -rn | head -20Цей конвеєр: знаходить усі рядки з помилками, сортує їх, підраховує унікальні входження, повторно сортує за частотою у спадному порядку та показує 20 найпоширеніших помилок. Це техніка першочергового сортування при будь-якому виробничому інциденті.
Пошук файлів, що містять шаблон, з подальшими діями над ними
grep -rl "deprecated_function" /var/www/html/ | xargs sed -i 's/deprecated_function/new_function/g'grep -rl виводить список файлів, що містять шаблон; xargs передає їх у sed для заміни на місці. Завжди спочатку тестуйте без -i або використовуйте -i.bak для створення резервних копій.
Пошук через SSH
ssh user@server "grep -r 'error' /var/log/app/" | lessВи можете запустити grep на віддаленому сервері та передавати результати до свого локального терміналу — корисно, коли файли журналів занадто великі для передачі.
Поєднання з awk для структурованого розбору
grep "POST /api" access.log | awk '{print $1, $7, $9}'grep фільтрує відповідні рядки; awk витягує конкретні поля (IP, URL, код статусу). Ця комбінація вирішує більшість завдань аналізу журналів без потреби у спеціалізованій платформі агрегації журналів.
Міркування щодо продуктивності
На великих файлах або при частій автоматизації ці оптимізації мають значення:
- Використовуйте
-Fдля літеральних рядків.grep -F "exact string"повністю обходить компіляцію регулярних виразів і є помітно швидшим. - Використовуйте
LC_ALL=C. ВстановленняLC_ALL=C grep "pattern" fileпримушує до обробки в однобайтовій локалі, що може бути в 2–5 разів швидше на UTF-8 файлах, оскільки пропускає обробку багатобайтових символів. - Уникайте
-rна мережевих файлових системах. Рекурсивний grep через NFS або CIFS може насичувати мережевий вввід/вивід. Натомість використовуйтеfindз-execта явним обмеженням шляху. - Використовуйте
--mmapна Linux.grep --mmapвикористовує відображення пам’яті замість системних викликівread(), що зменшує накладні витрати на великих файлах (доступно не на всіх платформах). - Паралелізуйте за допомогою
xargs -P. Для пошуку в багатьох незалежних файлах розподіліть навантаження:
find /var/log -name "*.log" | xargs -P 4 grep -l "error"Це запускає 4 процеси grep паралельно, використовуючи кілька ядер CPU.
grep порівняно з альтернативними інструментами пошуку
| Інструмент | Швидкість на великих репозиторіях | Підтримка регулярних виразів | Враховує `.gitignore` | Найкраще для |
|---|---|---|---|---|
grep | Помірна | BRE/ERE/PCRE | Ні | Системні файли, журнали, скриптинг |
ripgrep (rg) | Дуже швидка | PCRE2 | Так | Пошук коду в репозиторіях |
ag (Silver Searcher) | Швидка | PCRE | Так | Пошук коду, старша альтернатива rg |
ack | Помірна | PCRE | Частково | Кодові бази, орієнтовані на Perl |
fgrep / grep -F | Найшвидша | Відсутня (лише літерали) | Ні | Сканування журналів за фіксованими рядками |
Для завдань системного адміністрування — сканування /var/log, /etc або виведення активних процесів — grep залишається правильним інструментом, оскільки він доступний повсюдно без встановлення. Для пошуку в кодових базах застосунків ripgrep є значно швидшим і зручнішим.
Практичні реальні робочі процеси
Аудит невдалих спроб входу через SSH
grep -i "failed password" /var/log/auth.log | grep -oP "from K[d.]+" | sort | uniq -c | sort -rn | head -10Це витягує вихідний IP кожної невдалої спроби входу через SSH та ранжує їх за частотою — перший крок у виявленні джерел брутфорс-атак перед оновленням правил брандмауера.
Пошук помилок конфігурації перед перезапуском служби
grep -rn "listens*443" /etc/nginx/Підтверджує, які файли конфігурації Nginx визначають HTTPS-слухачів. Поєднайте з налаштуванням SSL Certificates, щоб перевірити, чи дійсно існують шляхи до сертифікатів, зазначені в цих файлах.
Моніторинг файлу журналу в реальному часі
tail -f /var/log/app/production.log | grep --line-buffered "ERROR"--line-buffered примушує grep скидати виведення після кожного рядка замість буферизації, що є обов’язковим при передачі даних з tail -f через конвеєр. Без цього ви можете не бачити жодного виведення протягом хвилин, навіть якщо збіги відбуваються.
Перевірка розгорнутої конфігурації
grep -c "server_name" /etc/nginx/sites-enabled/* | grep -v ":0"Виводить список кожного увімкненого сайту Nginx, що має принаймні одну директиву server_name — швидка перевірка після розгортання нового віртуального хоста в середовищі VPS Hosting.
Витягування адрес електронної пошти з файлу
grep -Eo "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}" contacts.txtПрапорець -o у поєднанні з шаблоном ERE витягує лише знайдені адреси електронної пошти, по одній на рядок, готові до подальшої обробки.
Пошук у журналах застосунків на кількох серверах
На Dedicated Server з кількома екземплярами застосунків може знадобитися зіставлення журналів із різних каталогів:
grep -rh --include="*.log" "transaction_id=abc123" /var/log/app1/ /var/log/app2/ /var/log/app3/-h придушує імена файлів, щоб виведення можна було передати по конвеєру в представлення, відсортоване за часовою міткою.
Поширені помилки та способи їх уникнення
Забуття взяти в лапки шаблони з пробілами:
# Wrong — shell splits "connection refused" into two arguments
grep connection refused /var/log/syslog
# Correct
grep "connection refused" /var/log/syslogВикористання синтаксису BRE там, де потрібен ERE:
# Wrong in BRE — + is literal
grep "error+" app.log
# Correct — use -E or escape in BRE
grep -E "error+" app.log
grep "error+" app.logРекурсивний пошук, що зачіпає бінарні файли:
# Produces "Binary file matches" noise
grep -r "config" /usr/
# Correct — skip binary files
grep -r --binary-files=without-match "config" /usr/
# or equivalently
grep -rI "config" /usr/Плутанина з прив’язками — ^ всередині класу символів:
[^abc] означає "не a, b або c". ^ означає "початок рядка" лише тоді, коли він з’являється на самому початку шаблону, поза дужками.
Ключові висновки та матриця прийняття рішень
Використовуйте цей контрольний список при складанні команди grep:
- Літеральний рядок, регулярний вираз не потрібен? Додайте
-Fдля максимальної швидкості. - Невідомий регістр у цільовому файлі? Додайте
-i. - Потрібно знати, де у файлі знаходиться збіг? Додайте
-n. - Пошук у дереві каталогів? Додайте
-r --include="*.ext"для обмеження області пошуку. - Великий файл, потрібно лише підтвердити наявність? Додайте
-m 1іgrepзавершить роботу після першого збігу. - Потрібен навколишній контекст для діагностики? Додайте
-C 3. - Шаблон містить метасимволи оболонки? Візьміть шаблон в одинарні лапки:
grep '$variable'. - Пошук у стиснутих журналах? Використовуйте
zgrepабоzcat file.gz | grep. - Потрібне чергування або квантифікатори
+/?? Додайте-Eдля ERE. - Потрібні випереджальні перевірки або нежадібне зіставлення? Додайте
-Pдля PCRE (лише GNU grep). - Витягування конкретного знайденого тексту, а не цілих рядків? Додайте
-o. - Пошук у кодовій базі, а не в системних файлах? Розгляньте
ripgrepнатомість.
При управлінні серверною інфраструктурою — чи то на VPS з cPanel, чи то в чистому середовищі Linux — grep є першим інструментом, до якого ви звертаєтеся, коли щось ламається. Засвоєння комбінацій прапорців та можливості поєднання з awk, sed, sort та xargs перетворює необроблені дані журналів на корисну діагностичну інформацію за лічені секунди.
Для середовищ, де Email Hosting або веб-застосунки генерують великі обсяги структурованих журналів, природним наступним кроком є поєднання grep з конвеєром агрегації журналів (стек ELK, Loki або подібні) — але grep залишається запасним варіантом, який працює скрізь, завжди, без жодних залежностей.
Часті запитання
У чому різниця між grep, egrep та fgrep?
grep за замовчуванням використовує базові регулярні вирази. egrep еквівалентний grep -E і використовує розширені регулярні вирази, де +, ?, | та () працюють без зворотних косих рисок. fgrep еквівалентний grep -F і трактує шаблон як фіксований літеральний рядок без інтерпретації регулярних виразів, що робить його найшвидшим варіантом. Обидва egrep та fgrep є застарілими псевдонімами; використовуйте grep -E та grep -F у скриптах.
Чому grep -r іноді повертає "Binary file matches"?
grep виявляє бінарні файли шляхом сканування на наявність нульових байтів. Коли він знаходить збіг у тому, що вважає бінарним файлом, він виводить це повідомлення замість рядка зі збігом. Придушіть бінарні файли за допомогою grep -rI (велика I) або примусово увімкніть текстовий режим обробки за допомогою grep -ra (обробляти всі файли як текст). Використовуйте -I у виробничому середовищі, щоб уникнути спотвореного виведення через випадкове зіставлення скомпільованих об’єктів або стиснутих файлів.
Як шукати шаблон, що містить пряму косу риску?
Прямі косі риски не мають спеціального значення в шаблонах grep (на відміну від sed або awk). Їх можна використовувати буквально: grep "var/log" /etc/logrotate.conf. Екранування не потрібне.
Який найшвидший спосіб перевірити, чи існує рядок у великому файлі?
Використовуйте grep -qF "string" file && echo "found". Прапорець -q придушує все виведення та завершує роботу зі статусом 0 при першому збігу, 1 якщо збігів немає. Прапорець -F вимикає обробку регулярних виразів. Разом grep читає лише стільки файлу, скільки потрібно, і негайно завершує роботу — критично важливо для файлів розміром у гігабайти.
Чи може grep шукати у файлах на віддаленому сервері без їх локального копіювання?
Так. Передайте через SSH: ssh user@host "grep -r 'pattern' /var/log/". Пошук виконується на віддаленому хості, і по мережі передаються лише рядки зі збігами. Для регулярних пошуків розгляньте можливість монтування віддаленої файлової системи за допомогою sshfs та локального запуску grep, або використовуйте централізоване рішення для збору журналів, якщо обсяг виправдовує інфраструктуру.
