Jak grepować 2 lub 3 wiersze, jeden zawierający tekst, który chcę, a pozostałe tuż pod nim?

32

To jest migawka dziennika błędów:

06:16:29,933 ERROR EmailRMManager$:45 - Exception In get Message
com.rabbitmq.client.AlreadyClosedException: clean connection shutdown; reason: Attempt to use closed channel
    at com.rabbitmq.client.impl.AMQChannel.ensureIsOpen(AMQChannel.java:195)
    at com.rabbitmq.client.impl.AMQChannel.rpc(AMQChannel.java:222)
    at com.rabbitmq.client.impl.AMQChannel.rpc(AMQChannel.java:208)
    at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:139)
    at com.rabbitmq.client.impl.ChannelN.basicGet(ChannelN.java:645)

Wykonuję następujące polecenie:

cat foo.log | grep ERROR dostać OP jako:

06:16:29,933 ERROR EmailRMManager$:45 - Exception In get Message

Jakie polecenie powinienem wykonać, aby uzyskać wynik jako

06:16:29,933 ERROR EmailRMManager$:45 - Exception In get Message
    com.rabbitmq.client.AlreadyClosedException: clean connection shutdown; reason: Attempt to use closed channel

tzn. czy grepować linie po wzorze?

theTuxRacer
źródło
Czy com.rabbitmq.clienttekst w następnym wierszu zaczyna się od początku, czy ma przed sobą jakieś spacje?
Eugen Konkov

Odpowiedzi:

62

Po prostu wykonaj:

grep -A1 ERROR

-A1Mówi grep zawierać 1 linię po meczu. -Bzawiera linie przed meczem, na wypadek, gdybyś też tego potrzebował.

Jeremy Kerr
źródło
och racja, to też byłoby pomocne.
theTuxRacer
12
I -Cobejmuje wiersze zarówno przed meczem, jak i po nim (uważam, że „C” oznacza „kontekst”).
Marius Gedminas
5

Bardziej przenośny sposób to awk

awk '/ERROR/{n=NR+1} n>=NR' foo.log

A może chcesz śledzić wszystkie wcięte linie?

awk '/^[^[:blank:]]/{p=0} /ERROR/{p=1} p' foo.log
geirha
źródło
2
: O, to dobra informacja, ale raczej przesada! niemniej jednak dobrze jest znać inną metodę :)
theTuxRacer
Chciałbym zrozumieć, jak działają te awkpolecenia.
Firefeather
3
@Firefeather awk.freeshell.org jest dobrym źródłem do nauki awk. Strona podręcznika GNU awk też jest całkiem dobra.
geirha
1

Znalazłem to rozwiązanie:

cat apache.error.log | grep -Pzo '^.*?Exception In get Message.*?\ncom\.rabbitmq.*?(\n(?=\s).*?)*$'

Gdzie (\n(?=\s).*?)*oznacza:

  • \n znajdź następny wiersz
  • (?=\s) gdzie zaczyna się od znaku spacji
  • .*? do końca linii
  • (...)* Znajdź takie linie wiele razy

PS. Możesz darniować ten wzór, \ncom\.rabbitmq.*?jeśli druga linia zaczyna się od białych znaków\s

Eugen Konkov
źródło