пытаюсь извлечь некоторые шаблоны на строку из файла журнала. Я пытаюсь извлечь первую временную метку и два или три других совпадения, но я хочу иметь возможность печатать только совпадения из строк, где появляются все совпадения. Есть ли одна команда grep, с помощью которой я могу это сделать, или мне нужно пройтись по каждой строке?
Мой лог-файл выглядит так:
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"}]
Я хочу иметь возможность извлекать определенные группы, такие как временная метка в начале, разделы «content» и «to_addr».
Я придумал следующее:
grep -oP '(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})|"to_addr":"\K(\d+)|"content":\K"(.+?)"' | tr -d '\n'
Но я не могу выбрать только те строки, где все три соответствия шаблону существуют. Пожалуйста, что я делаю не так? Я ожидаю слишком многого?
решение1
Вы используете ИЛИ |
между своими шаблонами, вам нужно И.
В вашем шаблоне вы ищете , "to_addr":"\K(\d+)
но в вашем примере значение to_addr
равно ABCD
, поэтому оно не совпадает с , и между и \d+
есть пробел , то же самое для ."to_addr:
"ABCD"
content
Если to_addr
всегда предшествует content
:
grep -P '^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.*?"to_addr": "\d+.*?"content": ".+?"'
В противном случае используйте опережающие просмотры:
grep -P '^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}(?=.*?"to_addr": "\d+)(?=.*?"content": "(.+?)")'
Если вы хотите вывести только совпадения, предлагаю однострочный код на Perl:
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