如何高效提取日志中时间戳与引号内内容并单行输出?
当然可以用单行命令高效实现,而且完全不需要循环处理!先帮你排查下之前命令的问题,再给几个靠谱的方案:
问题根源
你之前的命令之所以会出现换行异常、输出混乱,大概率是处理多文件时grep默认输出了文件名前缀(比如file.log:2018-05-14T...),导致sed的.{32}匹配到了文件名+部分时间戳,破坏了提取逻辑。加上grep -h参数就能解决这个问题(-h会让grep不输出文件名前缀)。
方案1:简洁的grep+sed组合(易读易写)
这个方案保留了你熟悉的工具链,修正后就能正常工作,而且效率足够应对海量日志:
grep -h "vendorCheck" "$INPUTDIR"/* | sed -E 's/^([0-9:T+-]{32}).*changed: "([^"]*)".*/\1 \2/'
grep -h "vendorCheck" "$INPUTDIR"/*:筛选出包含vendorCheck的行,且不输出文件名前缀sed -E:启用扩展正则,避免转义麻烦- 正则说明:
^([0-9:T+-]{32}):精准匹配开头32位的时间戳(比.{32}更可靠,不会误匹配非时间戳内容).*changed: "([^"]*)":匹配到changed: "后,提取直到下一个引号的内容([^"]*是非贪婪匹配,避免行内有多个引号时出错)\1 \2:输出提取到的时间戳和引号内的厂商字符串,用空格分隔
方案2:高效的单awk命令(推荐处理超大量文件)
awk可以一次性完成筛选、提取,不需要管道,减少进程开销,效率更高,适合你的海量日志场景:
awk '/vendorCheck/ {match($0, /^([0-9:T+-]{32}).*changed: "([^"]*)"/, arr); print arr[1], arr[2]}' "$INPUTDIR"/*
/vendorCheck/:先筛选出目标行match(...):用正则匹配行内容,把时间戳和厂商字符串存入数组arrprint arr[1], arr[2]:直接输出结果
如果你的awk版本较旧(不支持match的第三个参数),可以用兼容性更好的写法:
awk '/vendorCheck/ { time = substr($0, 1, 32); start = index($0, "changed: \"") + 10; end = index(substr($0, start), "\""); vendors = substr($0, start, end-1); print time, vendors }' "$INPUTDIR"/*
效果验证
用你给出的日志行测试,两个方案都会输出:
2018-05-14T10:10:22.769029+03:00 0403 14e1 05e3 05e3 03f0 0403 0bda 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b
完全符合你的需求,而且每条匹配结果都会单独成行,不会合并。
内容的提问来源于stack exchange,提问作者TimoM
相关产品推荐
相关产品推荐

