Das grep-Regex-Muster stimmt mit jeder Zeile überein, wobei nur alle Übereinstimmungen in derselben Zeile angezeigt und gedruckt werden.

Das grep-Regex-Muster stimmt mit jeder Zeile überein, wobei nur alle Übereinstimmungen in derselben Zeile angezeigt und gedruckt werden.

Ich versuche, aus einer Protokolldatei zeilenweise einige Muster zu extrahieren. Ich versuche, den ersten Zeitstempel und zwei oder drei weitere Übereinstimmungen zu extrahieren, möchte aber nur die Übereinstimmungen aus den Zeilen drucken können, in denen alle Übereinstimmungen vorkommen. Gibt es einen einzelnen Grep-Befehl, mit dem ich dies tun kann, oder muss ich jede Zeile durchlaufen?

Meine Logzeile sieht so aus

2018-08-07 08:55:20 ERROR[t-dispatcher-24] - Error while processing message: code:[RequestTimeout], message:[{"from_addr_type": null, "transport_name": "999_abc_999_2_1", "in_reply_to": null, "group": null, "timestamp": "2018-08-07 07:55:19.795748", "from_addr": "341231231234", "message_type": "user_message", "helper_metadata": {}, "to_addr": "ABCD", "to_addr_type": null, "session_id": "157692", "content": "0013091779", "routing_metadata": {}, "message_version": "20110921", "transport_type": "XXXX", "provider": "abc_somewhere", "transport_metadata": {"abc_somewhere_XXXX": {"clientId": "XXXX157692", "starCode": "999", "session_id": "157692", "phase": "2", "dcs": "15", "requestId": "157692"}}, "session_event": "resume", "message_id": "5d9cab5353ff449783a737e8390a690b"}]

Ich möchte in der Lage sein, bestimmte Gruppen zu extrahieren, wie etwa den Zeitstempel am Anfang, die Abschnitte „Inhalt“ und „An_Adresse“.

Mir ist Folgendes eingefallen: grep -oP '(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})|"to_addr":"\K(\d+)|"content":\K"(.+?)"' | tr -d '\n'

Aber ich kann nicht nur die Zeilen auswählen, in denen alle drei Musterübereinstimmungen vorhanden sind. Bitte, was mache ich falsch? Erwarte ich zu viel?

Antwort1

Sie verwenden ein ODER |zwischen Ihren Mustern, Sie möchten ein UND.

In Ihrem Muster suchen Sie nach, aber in Ihrem Beispiel ist "to_addr":"\K(\d+)der Wert von, also stimmt er nicht mit überein und zwischen und steht ein Leerzeichen , dasselbe gilt für .to_addrABCD\d+"to_addr:"ABCD"content

Wenn to_addrsteht immer vor content:

grep -P '^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.*?"to_addr": "\d+.*?"content": ".+?"' 

Andernfalls verwenden Sie Lookaheads:

grep -P '^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}(?=.*?"to_addr": "\d+)(?=.*?"content": "(.+?)")' 

Wenn Sie nur die Übereinstimmungen drucken möchten, schlage ich einen Perl-Einzeiler vor:

perl -ane 'print "$1\t$2\t$3\n" if (/^(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})(?=.*?"to_addr": "(\d+))(?=.*?"content": "(.+?)")/)' file

verwandte Informationen