ogonuj plik dziennika, ale pokaż tylko określone wiersze

29

Ogoniam plik dziennika flagą -f. Następnie przesyłam to do grep, aby znaleźć tylko linie zawierające „X”. To działa idealnie dobrze. Teraz chcę ponownie potokować to do innego grepa, który usunie wszystkie linie zawierające „Y”. Po dodaniu drugiego potoku plik przestaje się odświeżać i wygląda na to, że nie nadchodzą żadne dane.

To polecenie działa: tail -f my_file.log | grep "X"

To polecenie, które nie: tail -f my_file.log | grep "X" | grep -v "Y"

Jak powinienem to ustrukturyzować, aby polecenie działało?

Ori Horev
źródło
1
spróbuj zrobić jedną rurkę za rurą, zmień kolejność, zrób tail -f file|grep -v "Y". jeśli wynik jest w porządku, przejdź do dołączenia grep "X".
Aizuddin Zali

Odpowiedzi:

38

Ponieważ dane wyjściowe grepsą buforowane, użyj --line-bufferedopcji, grepaby włączyć buforowanie linii:

tail -f /path/to/log | grep --line-buffered 'X' | grep -v 'Y'

Jeśli grepnie masz takiej opcji, możesz użyć stdbufjako alternatywy:

tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
heemayl
źródło
1
Zastanawiam się, jak stdbufpowiedzieć, libstdbuf.sojakich ustawień użyć.
kasperd
@kasperd: Zmienne środowiskowe.
Nate Eldredge
1
@NateEldredge Już szukałem zmiennych środowiskowych w danych wyjściowych diff -u <(env) <(stdbuf env)i nie znalazłem żadnych. Ale teraz zdaję sobie sprawę, że powinienem był to przetestować diff -u <(env) <(stdbuf -oL env).
kasperd
Jestem również tego samego rodzaju problemem. w moim przypadku muszę wydrukować wszystkie wiersze zawierające „aaa” i „bbb”. Powyższe pierwsze rozwiązanie nie działa. Drugie rozwiązanie działa dla „aaa” istnieje i „bbb” nie istnieje. oba istnieją nie działają. nie daje wyników. moje polecenie wygląda tak: tail -f test.txt | stdbuf -oL grep 'aaa' | grep 'bbb' nie daje żadnego wyniku. Czy mógłbyś mi pomóc.
niedz.
18

Zwykle uważam, że jest bardziej przydatny awkdo tego rodzaju kontroli logicznych:

tail -f /path/to/log | awk '/X/ && !/Y/'
#                           ^^^    ^^^^
#                   this I want    but not this

Testowany przez dwie zakładki, jedną w której ciągle piszę, seq 20 >> myfilea drugą na przykład tail -f myfile | awk '/3/ && !/13/'.

fedorqui
źródło
15

Innym podejściem byłoby użycie pojedynczego grepwywołania zamiast dwóch, aby uniknąć problemu buforowania. Wystarczy użyć wyrażeń regularnych, które pasują do wierszy zawierających 0 lub więcej znaków innych niż Y, następnie X, a następnie 0 lub więcej znaków innych niż Y do końca wiersza „

tail -f /path/to/log | grep '^[^Y]*X[^Y]*$'
terdon
źródło