我需要从日志文件中提取消息。消息以两种不同的方式记录:在一行中,如下所示:
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
您可以使用
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}/nn&/' |
awk 'BEGIN { RS = "nn"; ORS=""} /XYZ/ {print}'
观看在线演示
详
sed -E 's/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}/nn&/'
- 此 sed 命令查找以日期时间格式开头的行,并在它们前面加上双换行符awk 'BEGIN { RS = "nn"; ORS=""} /XYZ/ {print}'
- 此 awk 命令通过"\"(RS
是记录分隔符(将文件拆分为记录时读取文件,并且仅打印(由于ORS=""
而省略nn
,其中ORS
是输出记录分隔符(包含XYZ
子字符串的那些。
使用 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
>
>