尝试从日志文件中每行提取一些模式。我尝试提取第一个时间戳和两个或三个其他匹配项,但我希望能够仅打印所有匹配项出现的行中的匹配项。是否有单个 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"}]
我希望能够提取某些组,例如开始时的时间戳、“内容”和“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
您在模式之间使用了 OR |
,而您想要的是 AND。
在您的模式中,您正在搜索,"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