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ę.