Arr*_*cal 2 sed awk text-processing gawk
我有一个报告进程输出的日志文件,我想从两个模式的最后一次出现之间提取所有行。
图案将沿线;
Summary process started at <datestring>
Run Code Online (Sandbox Code Playgroud)
和
Summary process finished at <datestring> with return code <num>
Run Code Online (Sandbox Code Playgroud)
整个文件中将有这些模式的几个实例,以及许多其他信息。我想打印唯一的最后一次出现。
我知道我可以使用:
sed -n '/StartPattern/,/EndPattern/p' FileName
Run Code Online (Sandbox Code Playgroud)
获取模式之间的线条,但不确定如何获取最后一个实例。sed 或 awk 解决方案就可以了。
编辑: 在检测到 StartPattern 后,当多个 StartPattern 出现而没有 EndPattern 时,或者文件末尾之前没有 EndPattern 时,我完全不清楚我想要的行为
对于缺少 EndPattern 的多个 StartPattern,我只想要从最后一个 StartPattern 到 EndPattern 的行。
对于在没有 EndPattern 的情况下到达 EOF 的 StartPattern,我希望一切都达到 EOF,然后输入一个字符串来警告到达 EOF。
你总是可以这样做:
tac < fileName | sed '/EndPattern/,$!d;/StartPattern/q' | tac
Run Code Online (Sandbox Code Playgroud)
如果您的系统没有 GNU tac
,您也许可以使用它tail -r
。
你也可以这样做:
awk '
inside {
text = text $0 RS
if (/EndPattern/) inside=0
next
}
/StartPattern/ {
inside = 1
text = $0 RS
}
END {printf "%s", text}' < filename
Run Code Online (Sandbox Code Playgroud)
但这意味着读取整个文件。
请注意,如果StartPattern
aStartPattern
和下一个之间有另一个,EndPattern
或者如果最后一个StartPattern
没有结尾,EndPattern
或者如果有与StartPattern
和匹配的行,它可能会给出不同的结果EndPattern
。
awk '
/StartPattern/ {
inside = 1
text = ""
}
inside {text = text $0 RS}
/EndPattern/ {inside = 0}
END {printf "%s", text}' < filename
Run Code Online (Sandbox Code Playgroud)
会使它的行为更像该tac+sed+tac
方法(未关闭的尾随StartPattern
情况除外)。
最后一个似乎最接近您编辑的要求。添加警告只是:
awk '
/StartPattern/ {
inside = 1
text = ""
}
inside {text = text $0 RS}
/EndPattern/ {inside = 0}
END {
printf "%s", text
if (inside)
print "Warning: EOF reached without seeing the end pattern" > "/dev/stderr"
}' < filename
Run Code Online (Sandbox Code Playgroud)
To avoid reading the whole file:
tac < filename | awk '
/StartPattern/ {
printf "%s", $0 RS text
if (!inside)
print "Warning: EOF reached without seeing the end pattern" > "/dev/stderr"
exit
}
/EndPattern/ {inside = 1; text = ""}
{text = $0 RS text}'
Run Code Online (Sandbox Code Playgroud)
Portability note: for /dev/stderr
, you need either a system with such a special file (beware that on Linux if stderr is open on a seekable file that will write the text at the beginning of the file instead of the current position within the file) or an awk
implementation that emulates it like gawk
, mawk
or busybox awk
(those work around the Linux issue mentioned above).
On other systems, you can replace print ... > "/dev/stderr"
with print ... | "cat>&2"
.