如何用sed/grep/awk/gawk提取日志文件中指定分隔符间的所有数据?
使用sed/grep/awk提取日志中两个分隔符之间的数据
没问题,我来帮你梳理下用sed、grep、awk这些工具提取日志中两个分隔符之间内容的实用方法,结合你给出的日志示例来逐个演示:
1. 用grep快速提取(适合简单场景)
如果你的需求是提取[和]之间的模块名(比如日志里的xml、properties),直接用grep的Perl正则模式就能搞定:
grep -oP '\[\K[^\]]+' your_log_file.log
简单解释:
-o:只输出匹配到的内容,不会整行输出-P:启用Perl兼容的正则语法,方便用更灵活的匹配规则\[\K:先匹配[,然后丢弃这个匹配结果(只保留后面的内容)[^\]]+:匹配所有不是]的字符,直到遇到]为止
对应你的日志示例,运行后会输出:
xml properties properties log
要是你想提取每条日志的核心内容(从日志级别到下一个时间戳之前的部分),可以用这个命令:
grep -oP '2018-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} \w+ \K.*?(?= 2018-|$)' your_log_file.log
这个命令会跳过开头的时间戳和日志级别,只提取后面的日志正文,直到遇到下一个时间戳或者行尾。
2. 用sed做精准替换提取
sed擅长文本替换,用它来提取分隔符内容也很顺手:
提取[和]之间的内容
sed -n 's/.*\[\([^]]*\)\].*/\1/p' your_log_file.log
解释:
-n:默认不输出任何行,只打印我们指定的内容s/.*\[\([^]]*\)\].*/\1/p:把整行内容替换成[和]之间捕获到的内容,然后打印出来
如果要提取日志正文(去掉时间戳和后续的时间戳),可以用两次替换:
sed -E 's/2018-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3} [A-Z]+ //; s/ 2018-.*$//' your_log_file.log
第一次替换删掉开头的时间戳和日志级别,第二次替换删掉后面可能出现的下一个时间戳及内容。
3. 用awk处理复杂场景
awk按字段处理文本的能力很强,适合更复杂的提取需求:
提取[和]之间的内容
直接把[和]设为字段分隔符,然后取第二个字段就行:
awk -F'[][]' '{print $2}' your_log_file.log
这个方法简单粗暴,效果和前面的grep、sed一致。
处理合并的日志(多行/多时间戳在一行的情况)
如果你的日志里有多条记录挤在同一行(比如你示例里最后一行的省略号情况),awk可以帮你拆分并提取每条日志的正文:
awk '{ for (i=1; i<=NF; i++) { if ($i ~ /^2018-/) { if (line != "") print line; line = ""; } line = line (line ? " " : "") $i; } if (line != "") print line; }' your_log_file.log
这个脚本会遍历每个字段,遇到以2018-开头的时间戳时,就把之前积累的日志内容打印出来,然后重置内容,最后处理剩下的部分,完美拆分合并的日志。
自定义分隔符的通用方法
要是你需要提取任意两个分隔符(比如START和END)之间的内容,调整一下规则就行:
- grep:
grep -oP 'START\K.*?(?=END)' your_log_file.log - sed:
sed -n 's/.*START\(.*\)END.*/\1/p' your_log_file.log - awk:
awk '/START/,/END/{print substr($0, index($0,"START")+5, index($0,"END")-index($0,"START")-5)}' your_log_file.log(注意这里的5是START的长度,要根据实际分隔符调整)
内容的提问来源于stack exchange,提问作者TerminatorX
相关产品推荐
相关产品推荐

