我想跟踪日志文件并仅打印与正则表达式模式匹配的文本块.*\n.*\nABC(.*\n){1-6}XYZ
。如果我的正则表达式已经错误,我想匹配这个例子:
TIMESTAMP HERE
LOG ENTRY HEADER
ABC
STUFF
...
STUFF
XYZ
或者我会怎样真的like 是仅当字符串“ZZZ”没有出现在匹配中的任何地方时才匹配上面的内容。
我的解决方案是执行以下操作:
tail -f file | egrep --line-buffered -B 2 -A 6
但显然这回报比我想要的要多得多。我也没有安装软件包的选项,但我确实有awk
并且sed
可用。
答案1
您可以选择从“TIMESTAMP”到“XYZ”的任何块,并通过 在块后面引入 NUL 作为分隔符sed
,然后通过其他工具筛选出来,例如grep
最后删除 NUL 字节:
tail -f file |
sed -n '/TIMESTAMP/,/XYZ/{/XYZ/s/$/\x00/;p}' |
grep -z 'ABC' |
grep -z -v 'ZZZ' |
tr -d '\x00'
答案2
您可以做的是确定开始和结束模式。例如,让我们使用TIMESTAMP HERE
andXYZ
来达到此目的,并使用 sed 来查找之间的所有行。
sed -n '/^TIMESTAMP HERE/,/^XYZ/p' logfile.txt
答案3
更新:
tail -f log | sed '/\n/!N;N;/\nABC$/!D;N;N;N;N;N;N;/ZZZ/d'
显示与模板匹配的行ABC
,如果没有模板,则显示前面 2 行和后面 6 行ZZZ
缓冲区中始终有 3 行。我们检查最后一项。如果没有匹配项,则删除第一个并将执行移至脚本的开头。如果有匹配,则再添加 6 行。打印的决定是根据模式进行匹配而做出的ZZZ
。
不匹配:
假设XYZ
模式必须匹配记录块的末尾。然后:
tail -f | sed ':1;N;/XYZ/!b1;/ZZZ/d'
我认为这里不需要无缓冲输出,但是-u
标志在sed
流编辑器中提供了此功能。
还可以输入记录块开头的模式:
tail -f | sed '/TIMESTAMP/!d;:1;N;/XYZ/!b1;/ZZZ/d'
上述脚本将从记录开始到结束的所有行添加到SED编辑器缓冲区(模式空间)中,并与模板进行匹配ZZZ
,从而确定删除整个记录或打印。
另一种选择是,如果日志块包含相同数量的行,那么可以按照您尝试使用egrep 时的需要精确地对它们进行计数和显示。
让我们选择加号 + 符号作为计数器。在此示例中,我们将数到 5,但您可以在此模板中更改它 - +\{5\}
:
tail -f log | sed ':1;x;s/$/+/;/+\{5\}/!{x;N;b1};s/.*//;x'
还可以通过模板添加帐号开头并删除:
tail -f log | sed '/TIMESTAMP/!d;:1;x;s/$/+/;/+\{5\}/!{x;N;b1};s/.*//;x;/ZZZ/d'
计数器的工作原理是这样的。 SED 编辑器有两个缓冲区 - 模式空间和保持空间。该字符串被写入模式空间。该x
命令更改两个缓冲区的内容,我们在保留空间的末尾写入一个加号,并检查它们的编号,如果模式匹配 5 则打印内容,否则我们添加下一行并增加计数器。 5 行匹配后,我们重置计数器并重复该过程。