grep 3 最近发生的事件和发生的一些行

emm*_*mma 2 unix perl grep tail

我有一个文件,如:

exception: anythinggggg...
exception: anythinggggg...
abchdhjsdhsd
ygsuhesnkc
exception: anythingggg...
exception: anything...
..
..
Run Code Online (Sandbox Code Playgroud)

我想 grep 最近出现的 2 次异常关键字以及它之前的 3 行和之后的 3 行。

我正在使用类似的东西

grep -C 3 exception | tail -12
Run Code Online (Sandbox Code Playgroud)

我在这里使用 tail -12 因为我想要每次出现 6 行和最近出现 2 行。当异常的发生彼此相距很远时,这可以正常工作,但是如果说两次发生都是连续的,则会给我带来无用的线条。

abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
exception
exception
exception
abcd
Run Code Online (Sandbox Code Playgroud)

在上述情况下,它给了我

abdgjsd
abdgjsd
abdgjsd
exception
exception
exception
abcd
Run Code Online (Sandbox Code Playgroud)

然而,我想要的是

abdgjsd
exception
exception -----------------> OUTPUT FOR FIRST OCCURRENCE
exception
abcd

abdgjsd
abdgjsd
exception-----------------> OUTPUT FOR SECOND OCCURRENCE
exception
exception
abcd
Run Code Online (Sandbox Code Playgroud)

还有其他方法吗?可能我还可以指定出现的次数,而不仅仅是 grep 行和尾部的一些输出。

zdi*_*dim 5

您得到的输出是因为在下一次匹配时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
Run Code Online (Sandbox Code Playgroud)

---打印输出的更容易审查。这将打印所需的输出。

-0777选项,可以发出声音的整个文件到$_变量,它是split由换行符。迭代遍历数组索引($#m是 的最后一个元素的索引@m)。的$bi$ei是开始/结束索引打印,不能为+/- 2附近的数组的开始和结束。

输出可以通过管道传输,tail但这不能自动化:如果匹配在最后两行内,则输出行将减少(一两行),因此需要知道输入以进行精确截止。或者在脚本中找到匹配的索引,@idx = grep { $m[$_] =~ /exception/} for 0..$#m;,并在条件中使用它来只打印最后两个。

如果你打算使用这样的东西,我会把它变成一个脚本。然后直接将所有行读入数组,提供命令行选项(如-Cin grep)等。

保持逐行处理会使工作变得更加复杂。我们需要跟踪匹配项,以便我们在阅读它们后可以打印以下行。但是这里我们需要多个这样的记录——对于下一个匹配项,如果它们在以下要打印的行内。