我有一个文件,例如:
exception: anythinggggg...
exception: anythinggggg...
abchdhjsdhsd
ygsuhesnkc
exception: anythingggg...
exception: anything...
..
..
我想 grep 最近 2 次出现的异常关键字及其前 3 行和后 3 行。
我正在使用类似的东西
grep -C 3 exception | tail -12
我在这里使用 tail -12,因为我想要每次出现 6 行和最近 2 次出现。当异常的出现彼此相距很远时,这工作得很好,但如果说两次出现是连续的,那么会给我无用的行。
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
exception
exception
exception
abcd
在上面的例子中,它给了我
abdgjsd
abdgjsd
abdgjsd
exception
exception
exception
abcd
但是,我想要的是
abdgjsd
exception
exception -----------------> OUTPUT FOR FIRST OCCURRENCE
exception
abcd
abdgjsd
abdgjsd
exception-----------------> OUTPUT FOR SECOND OCCURRENCE
exception
exception
abcd
还有其他方法吗?也许我还可以指定出现的次数,而不仅仅是 grep 行并尾部它的一些输出。
最佳答案
您得到的输出是因为 grep
在下一次匹配时停止打印上下文 (-C
)。我不知道如何让它表现出其他行为。
下面的脚本(写在命令行上)读取整个文件并形成一个行数组。然后它会遍历它并为每个匹配打印周围的两行,或者直到数组的开始/结束。
perl -MList::Util=min,max -0777 -wnE'
@m = split /\n/;
for (0..$#m) {
if ($m[$_] =~ /exception/) {
$bi = max(0,$_-2);
$ei = min($_+2, $#m);
say for @m[$bi..$ei];
say "---"
}
}
' input.txt
打印 ---
是为了更轻松地查看输出。这将打印所需的输出。
-0777
选项将整个文件slurp放入$_
变量中,即split
通过换行符。迭代遍历数组索引($#m
是 @m
最后一个元素的索引)。 $bi
和 $ei
是要打印的开始/结束索引,在数组的开头和结尾附近不能为 +/- 2。
输出可以通过管道传输到tail
,但这无法自动化:如果匹配项位于最后两行内,则输出行数将会减少(一两行),因此需要输入以精确切断而闻名。或者在脚本中查找匹配索引,@idx = grep { $m[$_] =~/exception/} for 0..$#m;
,并在条件中仅使用它打印最后两个。
如果你打算使用这样的东西,我会把它做成一个脚本。然后直接将所有行读入数组,提供命令行选项(如grep
中的-C
)等。
维护逐行处理会使工作变得更加复杂。我们需要跟踪匹配,以便在读取以下行后可以打印它们。但这里我们需要多个这样的记录——对于下一个匹配,如果它们位于要打印的以下行内。
关于perl - grep 3 最新出现的内容以及该出现周围的一些行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44491833/