解析具有单行和多行混合内容的日志

时间:2018-09-21 09:00:31

标签: regex

我需要从日志文件中提取消息。消息以两种不同的方式记录:在一行中,如下所示:

2018-09-21 10:03:54,145 <message-content>
2018-09-21 10:05:02,008 <next-message-content>

或类似以下几行:

2018-09-21 10:03:54,145 <message-content-part 1>
<message-content-part 2>
...
<message-content-part n>
2018-09-21 10:04:12,198 <next-message-content>

每条消息均以标题\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}开始。 每封邮件中都没有任何特定的结束标签。

我想提取带有特定文本的所有消息(单行和多行)。

例如,搜索“ XYZ”的输出可能是这样的:

2018-09-21 10:03:54,145 AAA BBB XYZ CCC
2018-09-21 10:10:55,347 BBB 
CCC XYZW 
DDD
2018-09-21 10:12:56,060 EEE XYZFFF
GGG 

2 个答案:

答案 0 :(得分:1)

您可以使用

cat file | \
  sed -E 's/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}/\n\n&/' | \
  awk 'BEGIN { RS = "\n\n"; ORS=""} /XYZ/ {print}'

请参见online demo

详细信息

  • sed -E 's/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}/\n\n&/'-此sed命令查找以datetime格式开头的行,并在其前面加上双换行符
  • awk 'BEGIN { RS = "\n\n"; ORS=""} /XYZ/ {print}'-此awk命令通过“ \ n \ n”(RS是记录分隔符)将文件拆分成记录来读取文件,并且仅打印(省略{{1} }的原因是\n\n,其中ORS=""是输出记录分隔符)包含ORS子字符串的那些。

答案 1 :(得分:-1)

使用perl。我在示例输入中又添加了2条消息,这些消息不应出现在输出中。

> cat pattern_xyz.dat
2018-09-21 10:03:54,145 AAA BBB XYZ CCC
2018-09-21 10:03:54,145 AAA BBB PPP CCC
2018-09-21 10:10:55,347 BBB
CCC XYZW
DDD
2018-09-21 10:12:56,060 EEE XYZFFF
GGG
2018-09-21 10:10:55,347 BBB
CCC QQQW
DDD
>
> cat pattern_xyz.pl
#!/usr/bin/perl
$file=$ARGV[0];
$x=`cat $file`;

while($x=~m/(^\d{4}-\d{2}-\d{2})(.+?)(\d{4}-\d{2}-\d{2})(.*)/osm)
{
$content="$1$2";
$x="$3$4";
if( $content=~/XYZ/  ) { print "$content"; }
}
> pattern_xyz.pl pattern_xyz.dat #executing script
2018-09-21 10:03:54,145 AAA BBB XYZ CCC
2018-09-21 10:10:55,347 BBB
CCC XYZW
DDD
2018-09-21 10:12:56,060 EEE XYZFFF
GGG
>
>