Jak używać polecenia `grep` do wyszukiwania informacji w plikach
Polecenie grep — skrót od Global Regular Expression Print — to narzędzie Unix/Linux, które skanuje jeden lub więcej plików wiersz po wierszu i wyświetla każdy wiersz pasujący do podanego wzorca. Jest to de facto standard wyszukiwania tekstu w każdym systemie zgodnym z POSIX, obsługuje zarówno podstawowe, jak i rozszerzone wyrażenia regularne, co umożliwia dopasowywanie wszystkiego — od prostego ciągu znaków po złożone wzorce wieloznakowe.
Jeśli potrzebujesz możliwie najkrótszej odpowiedzi: uruchom grep "pattern" filename, aby przeszukać plik, dodaj -r, aby rekurencyjnie przeszukać drzewo katalogów, -i do dopasowania bez uwzględniania wielkości liter, a -n, aby wyświetlić numery wierszy obok wyników. Poniższe sekcje omawiają temat znacznie głębiej — obejmują rzeczywiste przepływy pracy, pułapki wydajnościowe oraz zaawansowane techniki wyrażeń regularnych, które większość poradników całkowicie pomija.
Co grep faktycznie robi pod maską
grep odczytuje dane wejściowe wiersz po wierszu i stosuje automat skończony wyprowadzony z podanego wyrażenia regularnego do każdego wiersza. Implementacja GNU (domyślna w systemie Linux) używa algorytmu Boyer-Moore-Horspool dla ciągów literalnych oraz konstrukcji Thompson NFA dla wzorców wyrażeń regularnych. Ta architektura sprawia, że grep jest niezwykle szybki na dużych plikach — unika nawrotów, w przeciwieństwie do narzędzi opartych na PCRE, takich jak perl czy python.
W rodzinie GNU coreutils istnieją trzy odrębne pliki binarne:
| Polecenie | Silnik | Zastosowanie |
|---|---|---|
grep | BRE / ERE (z -E) | Ogólne dopasowywanie wierszy |
egrep | ERE (rozszerzone wyrażenia regularne) | Skrót dla grep -E |
fgrep | Tylko ciągi stałe | Najszybszy; bez interpretacji wyrażeń regularnych |
zgrep | BRE / ERE na skompresowanych plikach | Archiwa .gz, .bz2 |
pgrep | Dopasowywanie nazw procesów | Przeszukuje tablicę procesów, nie pliki |
egrep i fgrep to przestarzałe aliasy w nowoczesnych systemach; w skryptach należy używać odpowiednio grep -E i grep -F dla zachowania przenośności.
Podstawowa składnia
grep [options] pattern [file ...]- pattern — ciąg znaków lub wyrażenie regularne ujęte w cudzysłów
- file — jedna lub więcej ścieżek do plików; pominięcie powoduje odczyt ze standardowego wejścia
- options — flagi modyfikujące zachowanie dopasowywania, format wyjścia lub wydajność
Minimalny przykład wyszukujący każdy wiersz zawierający słowo „error” w syslog:
grep "error" /var/log/syslogZawsze ujmuj wzorzec w cudzysłów. Wzorce bez cudzysłowów zawierające metaznaki powłoki (*, ?, [, $) zostaną rozwinięte przez powłokę, zanim grep je zobaczy, co prowadzi do cichych, nieprawidłowych wyników.
Podstawowe opcje, które każdy administrator musi znać
Przeszukiwanie wielu plików i katalogów
Podaj pliki jawnie lub użyj globowania powłoki:
grep "error" access.log error.log debug.log
grep "error" *.logAby przeszukać całe drzewo katalogów, użyj -r (podążaj za dowiązaniami symbolicznymi za pomocą -R):
grep -r "error" /var/log/Pułapka: Na serwerach produkcyjnych z głęboko zagnieżdżonymi hierarchiami logów, nieograniczone -r może generować znaczące obciążenie I/O. Ogranicz zakres za pomocą --include, aby uniknąć skanowania plików binarnych lub nieistotnych rozszerzeń:
grep -r --include="*.log" "error" /var/log/Wyszukiwanie bez uwzględniania wielkości liter (-i)
grep -i "error" application.logDopasowuje to error, Error, ERROR, eRrOr i każdą inną kombinację wielkości liter. Wewnętrznie GNU grep z flagą -i konwertuje zarówno wzorzec, jak i dane wejściowe na małe litery przed porównaniem, co powoduje niewielkie obciążenie przy bardzo dużych plikach.
Wyświetlanie numerów wierszy (-n)
grep -n "error" application.logPrzykładowe wyjście:
25:error occurred during processing
103:error: connection refusedNumery wierszy są niezbędne, gdy chcesz przejść bezpośrednio do dopasowania w edytorze: vim +25 application.log otwiera plik w wierszu 25.
Liczenie dopasowań (-c)
grep -c "error" application.logZwraca tylko liczbę pasujących wierszy, a nie same wiersze. Podczas przeszukiwania wielu plików każdy plik otrzymuje własną liczbę:
grep -c "error" *.logaccess.log:0
debug.log:14
error.log:3Odwrócone dopasowanie (-v)
grep -v "error" application.logZwraca każdy wiersz, który nie pasuje do wzorca. Praktyczne zastosowanie: usunięcie wierszy komentarzy z pliku konfiguracyjnego przed przekazaniem go dalej potokiem:
grep -v "^#" /etc/nginx/nginx.conf | grep -v "^$"Usuwa to zarówno wiersze komentarzy (zaczynające się od #), jak i puste wiersze, pozostawiając tylko aktywne dyrektywy.
Dopasowywanie całych słów (-w)
grep -w "error" application.logBez -w wyszukiwanie error dopasowałoby również errors, error_code i myerror. Flaga -w kotwi dopasowanie do granic słów, definiowanych jako przejścia między znakami słownymi ([a-zA-Z0-9_]) a znakami niesłownymi.
Ograniczanie liczby wierszy wyjściowych (-m)
grep -m 5 "error" application.loggrep zatrzymuje odczytywanie pliku po znalezieniu 5 pasujących wierszy. W przypadku pliku logu o rozmiarze 10 GB, gdy wystarczy potwierdzić istnienie wzorca, -m 1 może skrócić czas wykonania z sekund do milisekund, ponieważ grep kończy działanie natychmiast po pierwszym dopasowaniu.
Wiersze kontekstu (-A, -B, -C)
Jedna z najrzadziej używanych funkcji. Podczas diagnozowania błędu otaczające wiersze często zawierają przyczynę źródłową:
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)To różnica między zobaczeniem error: connection refused a zobaczeniem pełnego śladu stosu lub poprzedzającego żądania, które go wywołało.
Podświetlanie kolorami (--color)
grep --color=auto "error" application.logWiększość dystrybucji ustawia alias grep='grep --color=auto' w /etc/profile.d/ lub ~/.bashrc. Użyj --color=always podczas przekazywania potokiem do less -R, aby zachować kody ANSI:
grep --color=always "error" application.log | less -RWyświetlanie tylko pasującej części (-o)
Domyślnie grep wyświetla cały pasujący wiersz. Flaga -o wyświetla tylko tę część wiersza, która pasuje do wzorca:
grep -o "192.[0-9]*.[0-9]*.[0-9]*" access.logWyodrębnia to każdy adres IPv4 z logu dostępu — jeden adres na wiersz wyjściowy — co jest idealne do przekazania potokiem do sort | uniq -c | sort -rn w celu znalezienia najbardziej aktywnych klientów.
Pomijanie nazwy pliku w wyjściu (-h) i wymuszanie jej (-H)
Podczas przeszukiwania wielu plików grep poprzedza każde dopasowanie nazwą pliku. -h pomija tę informację; -H wymusza jej wyświetlanie nawet przy przeszukiwaniu jednego pliku. Używaj -H w skryptach, aby zagwarantować spójny format wyjścia niezależnie od liczby przekazanych plików.
Wyświetlanie tylko nazw plików (-l i -L)
grep -l "error" *.log # files that contain the pattern
grep -L "error" *.log # files that do NOT contain the patternPrzydatne w skryptach wdrożeniowych do identyfikowania plików konfiguracyjnych odwołujących się do przestarzałego parametru.
Wyrażenia regularne w grep
Podstawowe wyrażenia regularne (BRE)
grep domyślnie używa BRE. Kluczowe metaznaki:
| Metaznak | Znaczenie | Przykład |
|---|---|---|
^ | Początek wiersza | grep "^error" — wiersze zaczynające się od „error” |
$ | Koniec wiersza | grep "error$" — wiersze kończące się na „error” |
. | Dowolny pojedynczy znak | grep "err.r" — dopasowuje „error”, „errar” itp. |
* | Zero lub więcej poprzedniego | grep "err*" — „er”, „err”, „errr” itp. |
[abc] | Klasa znaków | grep "[aeiou]" — dowolna samogłoska |
[^abc] | Zanegowana klasa | grep "[^0-9]" — dowolny znak niebędący cyfrą |
| Ucieczka metaznaku | grep "." — dosłowna kropka |
W BRE znaki +, ?, {, }, (, ) i | muszą być poprzedzone ukośnikiem odwrotnym, aby były traktowane jako metaznaki. Jest to częste źródło pomyłek podczas przełączania się między BRE a ERE.
Rozszerzone wyrażenia regularne (ERE) z -E
grep -E "error|failure|critical" application.logERE upraszcza składnię — +, ?, |, () i {} działają bez ukośników odwrotnych:
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 levelsWyrażenia regularne zgodne z Perl (PCRE) z -P
GNU grep obsługuje PCRE za pomocą flagi -P, odblokowując wyprzedzenia, wsteczne odwołania i kwantyfikatory niezachłanne:
grep -P "(?<=user=)w+" auth.log # extract username after "user="
grep -P "d{4}-d{2}-d{2}" app.log # ISO date formatWażne: -P jest rozszerzeniem GNU i nie jest dostępne w BSD grep (domyślnym na macOS). Skrypty używające -P nie są przenośne bez zainstalowania GNU grep (brew install grep na macOS).
Przeszukiwanie skompresowanych plików za pomocą zgrep
Rotacja logów zazwyczaj kompresuje starsze logi za pomocą gzip. zgrep pozwala przeszukiwać je bez ręcznej dekompresji:
zgrep "error" /var/log/syslog.2.gzDla plików .bz2 użyj bzgrep. Dla plików .xz użyj xzgrep. Jeśli chcesz przeszukać zarówno skompresowane, jak i nieskompresowane logi jednym poleceniem:
zgrep -r "error" /var/log/Przypadek brzegowy: zgrep wewnętrznie wywołuje zcat do dekompresji, a następnie przekazuje wynik potokiem do grep. Nie obsługuje wszystkich flag grep. Jeśli potrzebujesz -P lub -o na skompresowanych plikach, najpierw zdekompresuj do pliku tymczasowego lub użyj zcat file.gz | grep -P "pattern".
Łączenie grep z innymi poleceniami
Prawdziwa moc grep ujawnia się, gdy jest łączony z innymi narzędziami za pomocą potoków.
Filtrowanie wyjścia procesów
ps aux | grep "[n]ginx"Sztuczka z nawiasem [n]ginx zapobiega pojawianiu się samego procesu grep w wynikach, ponieważ wzorzec [n]ginx nie pasuje do dosłownego ciągu [n]ginx na liście procesów.
Wyodrębnianie i agregowanie danych z logów
grep "error" application.log | sort | uniq -c | sort -rn | head -20Ten potok: znajduje wszystkie wiersze z błędami, sortuje je, zlicza unikalne wystąpienia, ponownie sortuje malejąco według częstotliwości i wyświetla 20 najczęstszych błędów. Jest to technika wstępnej triażu przy każdym incydencie produkcyjnym.
Znajdowanie plików zawierających wzorzec, a następnie działanie na nich
grep -rl "deprecated_function" /var/www/html/ | xargs sed -i 's/deprecated_function/new_function/g'grep -rl wyświetla pliki zawierające wzorzec; xargs przekazuje je do sed w celu zastąpienia w miejscu. Zawsze najpierw testuj bez -i lub użyj -i.bak, aby tworzyć kopie zapasowe.
Wyszukiwanie przez SSH
ssh user@server "grep -r 'error' /var/log/app/" | lessMożesz uruchomić grep na zdalnym serwerze i przesyłać wyniki strumieniowo do lokalnego terminala — przydatne, gdy pliki logów są zbyt duże do transferu.
Łączenie z awk do strukturalnego parsowania
grep "POST /api" access.log | awk '{print $1, $7, $9}'grep filtruje odpowiednie wiersze; awk wyodrębnia konkretne pola (IP, URL, kod statusu). Ta kombinacja obsługuje większość zadań analizy logów bez potrzeby dedykowanej platformy agregacji logów.
Kwestie wydajnościowe
W przypadku dużych plików lub automatyzacji o wysokiej częstotliwości te optymalizacje mają znaczenie:
- Używaj
-Fdla ciągów literalnych.grep -F "exact string"całkowicie pomija kompilację wyrażeń regularnych i jest mierzalnie szybszy. - Używaj
LC_ALL=C. UstawienieLC_ALL=C grep "pattern" filewymusza przetwarzanie w trybie jednobajtowym, co może być 2–5 razy szybsze na plikach UTF-8, ponieważ pomija obsługę znaków wielobajtowych. - Unikaj
-rna sieciowych systemach plików. Rekurencyjny grep przez NFS lub CIFS może nasycić sieciowe I/O. Zamiast tego używajfindz-execi jawnym określeniem zakresu ścieżek. - Używaj
--mmapna Linux.grep --mmapużywa wejścia/wyjścia mapowanego w pamięci zamiast wywołań systemowychread(), co zmniejsza narzut przy dużych plikach (niedostępne na wszystkich platformach). - Zrównoleglaj za pomocą
xargs -P. Przy przeszukiwaniu wielu niezależnych plików podziel obciążenie:
find /var/log -name "*.log" | xargs -P 4 grep -l "error"Uruchamia to 4 procesy grep równolegle, wykorzystując wiele rdzeni CPU.
grep a alternatywne narzędzia wyszukiwania
| Narzędzie | Szybkość na dużych repozytoriach | Obsługa wyrażeń regularnych | Respektuje `.gitignore` | Najlepsze zastosowanie |
|---|---|---|---|---|
grep | Umiarkowana | BRE/ERE/PCRE | Nie | Pliki systemowe, logi, skrypty |
ripgrep (rg) | Bardzo szybka | PCRE2 | Tak | Wyszukiwanie kodu w repozytoriach |
ag (Silver Searcher) | Szybka | PCRE | Tak | Wyszukiwanie kodu, starsza alternatywa dla rg |
ack | Umiarkowana | PCRE | Częściowo | Bazy kodu zorientowane na Perl |
fgrep / grep -F | Najszybsza | Brak (tylko ciągi stałe) | Nie | Skanowanie logów pod kątem stałych ciągów |
Do zadań administracji systemem — skanowania /var/log, /etc lub wyjścia aktywnych procesów — grep pozostaje właściwym narzędziem, ponieważ jest powszechnie dostępny bez instalacji. Do przeszukiwania baz kodu aplikacji ripgrep jest znacznie szybszy i wygodniejszy.
Praktyczne rzeczywiste przepływy pracy
Audyt nieudanych logowań SSH
grep -i "failed password" /var/log/auth.log | grep -oP "from K[d.]+" | sort | uniq -c | sort -rn | head -10Wyodrębnia to źródłowy IP każdej nieudanej próby logowania SSH i klasyfikuje je według częstotliwości — jest to pierwszy krok w identyfikowaniu źródeł ataków brute-force przed aktualizacją reguł zapory sieciowej.
Znajdowanie błędów konfiguracji przed ponownym uruchomieniem usługi
grep -rn "listens*443" /etc/nginx/Potwierdza, które pliki konfiguracyjne Nginx definiują nasłuchiwanie HTTPS. Połącz z konfiguracją Certyfikatów SSL, aby sprawdzić, czy ścieżki certyfikatów wskazane w tych plikach faktycznie istnieją.
Monitorowanie pliku logu w czasie rzeczywistym
tail -f /var/log/app/production.log | grep --line-buffered "ERROR"--line-buffered wymusza na grep opróżnianie bufora wyjściowego po każdym wierszu zamiast buforowania, co jest niezbędne przy przekazywaniu potokiem z tail -f. Bez tego możesz nie widzieć żadnego wyjścia przez minuty, mimo że dopasowania są znajdowane.
Weryfikacja wdrożonej konfiguracji
grep -c "server_name" /etc/nginx/sites-enabled/* | grep -v ":0"Wyświetla każdą włączoną witrynę Nginx zawierającą co najmniej jedną dyrektywę server_name — szybka kontrola poprawności po wdrożeniu nowego wirtualnego hosta w środowisku VPS Hosting.
Wyodrębnianie adresów e-mail z pliku
grep -Eo "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}" contacts.txtFlaga -o w połączeniu ze wzorcem ERE wyodrębnia tylko dopasowane adresy e-mail, jeden na wiersz, gotowe do dalszego przetwarzania.
Przeszukiwanie logów aplikacji na wielu serwerach
Na Serwerze Dedykowanym obsługującym wiele instancji aplikacji może być konieczne korelowanie logów z różnych katalogów:
grep -rh --include="*.log" "transaction_id=abc123" /var/log/app1/ /var/log/app2/ /var/log/app3/-h pomija nazwy plików, dzięki czemu wyjście można przekazać potokiem do widoku posortowanego według znacznika czasu.
Typowe błędy i jak ich unikać
Zapominanie o cudzysłowach wokół wzorców ze spacjami:
# Wrong — shell splits "connection refused" into two arguments
grep connection refused /var/log/syslog
# Correct
grep "connection refused" /var/log/syslogUżywanie składni BRE zamiast 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.logRekurencyjne wyszukiwanie trafiające na pliki binarne:
# 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/Mylące kotwiczenie — ^ wewnątrz klasy znaków:
[^abc] oznacza „nie a, b ani c”. Znak ^ oznacza „początek wiersza” tylko wtedy, gdy pojawia się na samym początku wzorca, poza nawiasami.
Kluczowe wnioski i macierz decyzyjna
Użyj tej listy kontrolnej podczas konstruowania polecenia grep:
- Ciąg literalny, bez potrzeby wyrażeń regularnych? Dodaj
-Fdla maksymalnej szybkości. - Nieznana wielkość liter w docelowym pliku? Dodaj
-i. - Potrzebujesz wiedzieć, gdzie w pliku jest dopasowanie? Dodaj
-n. - Przeszukujesz drzewo katalogów? Dodaj
-r --include="*.ext", aby ograniczyć zakres wyszukiwania. - Duży plik, wystarczy potwierdzić istnienie? Dodaj
-m 1, agrepzakończy działanie po pierwszym dopasowaniu. - Potrzebujesz otaczającego kontekstu do diagnozy? Dodaj
-C 3. - Wzorzec zawiera metaznaki powłoki? Ujmij wzorzec w pojedyncze cudzysłowy:
grep '$variable'. - Przeszukujesz skompresowane logi? Użyj
zgreplubzcat file.gz | grep. - Potrzebujesz alternacji lub kwantyfikatorów
+/?? Dodaj-Edla ERE. - Potrzebujesz wyprzedzeń lub dopasowywania niezachłannego? Dodaj
-Pdla PCRE (tylko GNU grep). - Wyodrębniasz konkretny dopasowany tekst, a nie całe wiersze? Dodaj
-o. - Przeszukujesz bazę kodu, a nie pliki systemowe? Rozważ użycie
ripgrep.
Zarządzając infrastrukturą serwerową — czy to na VPS z cPanel, czy w czystym środowisku Linux — grep jest pierwszym narzędziem, po które sięgasz, gdy coś przestaje działać. Opanowanie kombinacji jego flag i możliwości łączenia z awk, sed, sort i xargs pozwala w ciągu sekund przekształcić surowe dane z logów w użyteczne informacje diagnostyczne.
W środowiskach, gdzie Hosting Poczty E-mail lub aplikacje webowe generują duże ilości ustrukturyzowanych logów, naturalnym kolejnym krokiem jest połączenie grep z potokiem agregacji logów (stos ELK, Loki lub podobne) — jednak grep pozostaje rozwiązaniem awaryjnym działającym wszędzie, zawsze, bez żadnych zależności.
Często zadawane pytania
Jaka jest różnica między grep, egrep i fgrep?
grep domyślnie używa podstawowych wyrażeń regularnych. egrep jest równoważne grep -E i używa rozszerzonych wyrażeń regularnych, gdzie +, ?, | i () działają bez ukośników odwrotnych. fgrep jest równoważne grep -F i traktuje wzorzec jako dosłowny ciąg stały bez interpretacji wyrażeń regularnych, co czyni go najszybszą opcją. Zarówno egrep, jak i fgrep to przestarzałe aliasy; w skryptach używaj odpowiednio grep -E i grep -F.
Dlaczego grep -r czasami zwraca komunikat „Binary file matches”?
grep wykrywa pliki binarne, skanując w poszukiwaniu bajtów zerowych. Gdy znajdzie dopasowanie w pliku uznanym za binarny, wyświetla ten komunikat zamiast pasującego wiersza. Pomiń pliki binarne za pomocą grep -rI (wielka litera I) lub wymuś tryb tekstowy za pomocą grep -ra (traktuj wszystkie pliki jako tekst). Używaj -I w środowisku produkcyjnym, aby uniknąć zniekształconego wyjścia spowodowanego przypadkowym dopasowaniem skompilowanych obiektów lub skompresowanych plików.
Jak wyszukiwać wzorzec zawierający ukośnik?
Ukośniki nie mają specjalnego znaczenia we wzorcach grep (w przeciwieństwie do sed czy awk). Możesz ich używać dosłownie: grep "var/log" /etc/logrotate.conf. Nie jest wymagane żadne ucieczka.
Jaki jest najszybszy sposób sprawdzenia, czy ciąg istnieje gdziekolwiek w dużym pliku?
Użyj grep -qF "string" file && echo "found". Flaga -q pomija wszystkie wyjście i kończy działanie ze statusem 0 przy pierwszym dopasowaniu lub 1 w przypadku braku dopasowania. Flaga -F wyłącza przetwarzanie wyrażeń regularnych. Łącznie grep odczytuje tylko tyle pliku, ile potrzeba, i natychmiast kończy działanie — co jest kluczowe dla plików o rozmiarze gigabajtów.
Czy grep może przeszukiwać pliki na zdalnym serwerze bez kopiowania ich lokalnie?
Tak. Przekaż przez SSH: ssh user@host "grep -r 'pattern' /var/log/". Wyszukiwanie wykonuje się na zdalnym hoście i tylko pasujące wiersze są przesyłane przez sieć. W przypadku powtarzających się wyszukiwań rozważ zamontowanie zdalnego systemu plików za pomocą sshfs i uruchamianie grep lokalnie, lub użyj scentralizowanego rozwiązania do zbierania logów, jeśli wolumen to uzasadnia.
