Das grep regex-Muster stimmt in jeder Zeile überein, wobei nur alle Übereinstimmungen in derselben Zeile erscheinen und gedruckt werden

329
Sina

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

Meine Protokollzeile ist so

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 bestimmte Gruppen wie den Zeitstempel am Anfang, die Abschnitte "content" und "to_addr" extrahieren können.

Ich kam dazu: grep -oP '(\d-\d-\d\s\d:\d:\d)|"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?

0

1 Antwort auf die Frage

0
Toto

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

In Ihrem Muster, bist du "to_addr":"\K(\d+)aber ich Ihr Beispiel für den Wert to_addrist, ABCDdamit es nicht mit übereinstimmen \d+und es gibt einen Raum zwischen "to_addr:und "ABCD", gleich für content.

Wenn to_addrimmer vor content:

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

Sonst nur Lookaheads verwenden:

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

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

perl -ane 'print "$1\t$2\t$3\n" if (/^(\d-\d-\d\s\d:\d:\d)(?=.*?"to_addr": "(\d+))(?=.*?"content": "(.+?)")/)' file 
Danke vielmals! Dadurch kann ich die Zeilen perfekt auswählen, aber wie kann ich nur die Übereinstimmungen aus jeder Zeile in derselben Zeile drucken? Sina vor 5 Jahren 0
@ Sina: Ich schlage vor, einen Perl-Einzeiler zu verwenden, siehe meine Bearbeitung. Toto vor 5 Jahren 0
Vielen Dank! Sehr schöner Einliner! Ich habe ein kleines Skript gemacht: `while IFS = '' read -r line; do value0 = $ (echo "$ line" | grep -oP '^ (\ d - \ d - \ d \ s \ d : \ d : \ d ) '); value1 = $ (echo "$ line" | grep -oP '"bis_addr": "\ K (\ d +)'); value2 = $ (echo" $ line "| grep -oP '" content ":" \ K ( . +? ") '); printf"% s% s% s \ n "" $ value0 "" $ value1 "" $ value2 "; fertig> output_file` aber ich bin immer dankbar, perl zu bekommen. Sina vor 5 Jahren 0