Blog

Grep - znalezienie linii ale wyświetlenie innej

Naturalnie na linuxie do przeszukiwania plików tekstowych wykorzystuje się polecenie grep. Jestem do niego tak przyzwyczajony, że w sumie korzystam z niego bezwiednie. Niesłusznie, ponieważ ma trochę ciekawy funkcji do zaproponowania.

Przeszukiwałem ostatnio logi aplikacji, w których wpis składa się z trzech linii, więc w wynikach potrzebowałem wyświetlić inną linię niż ta która pasowała do wyrażenia regularnego. Normalnie, to napisałbym szybki skrypt bashowy, który mi obsłuży ten przypadek, ale wiedziony na stackoverflow - a jakże - trafiłem na proste i skuteczne rozwiązanie.

Grep posiada flagi kontekstowe linii, takie jak:

-A NUM, --after-context=NUM
Print  NUM  lines  of  trailing  context after matching lines.  Places a line containing a group separator (--) between contiguous groups of matches.  With the -o or --only-matching option, this has no effect and a warning is given.

-B NUM, --before-context=NUM
Print NUM lines of leading context before matching lines.  Places a line containing a group separator (--) between contiguous groups of matches.  With the -o or --only-matching option, this  has  no  effect  and  a warning is given.

-C NUM, -NUM, --context=NUM
Print NUM lines of output context.  Places a line containing a group separator (--) between contiguous groups of matches.  With the -o or --only-matching option, this has no effect and a warning is given.

Każdy z parametrów oddziela wyniki podwójnym myślinikiem.

Jako, że jeden obraz to tysiąc słów, przejdźmy do prostych przykładów.

Dla przykładowego pliku

2021-12-01
line A 1
line A 2
line A 3
2021-12-01
line B 1
line B 2
line B 3
2021-12-02
line C 1
line C 2
line C 3
2021-12-02
line D 1
line D 2
line D 3

Tłumaczę i objaśniam

Przypadek pierwszy z parametrem A: interesuje Nas zawartość drugiej linii po dacie 2 grudnia, czyli

$grep 12-02 -A2 grep.txt
2021-12-02
line C 1
line C 2
--
2021-12-02
line D 1
line D 2

Przypadek drugi z parameterm B: interesuje Nas zawartość linii o jedną wyżej przed linią zawierająca cyfrę "2"

$ grep 'line.*2' -B1 grep.txt
line A 1
line A 2
--
line B 1
line B 2
--
line C 1
line C 2
--
line D 1
line D 2

Przypadek trzeci z parametrem C: łączy parameter A i B i wyświetla zawartość linii przed i po o podaną wielkość. Uwaga, jeżeli wyniki nakładają się na siebie to linie się nie dublują, czyli

$ grep 'line.*2' -C2 grep.txt
2021-12-01
line A 1
line A 2
line A 3
2021-12-01
line B 1
line B 2
line B 3
2021-12-02
line C 1
line C 2
line C 3
2021-12-02
line D 1
line D 2
line D 3

Wyświetli cały plik - bez separatorów - ponieważ po dwie linie w dół i w górę od wyników nie ma nic ponad to co widać.

Dziękuję za uwagę.