grep 3最新发生的事件和一些线路发生 [英] grep 3 latest occurences and some lines around the occurence

查看:151
本文介绍了grep 3最新发生的事件和一些线路发生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文件:

  exception:anythinggggg ... 
exception:anythinggggg ...
abchdhjsdhsd
ygsuhesnkc
例外:anythingggg ...
例外:任何...
..
..

我想grep最近发生的两次异常关键字,以及之前的3行和后面的3行。



我正在使用类似于

  grep -C 3异常| tail -12 

我在这里使用尾部-12,因为我想每次出现6行,最近出现2次。这种情况很好,当异常发生时彼此远离,但如果说这两个事件都是连续的,就会给我无用的线。

  abdgjsd 
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
例外
例外
例外
abcd

在上面的例子中,它给了我

  abdgjsd 
abdgjsd
abdgjsd
例外
例外
例外
abcd

然而,我想要的是

  abdgjsd 
异常
异常----------------->首次发生的产量
例外
abcd

abdgjsd
abdgjsd
例外----------------- >第二次发生的产量
例外
例外
abcd

另一种方式呢?或许我也可以指定出现次数,而不仅仅是grep行和尾部输出。 你得到的输出是因为 grep 在下一场比赛中停止打印上下文( -C )。我没有看到如何让它表现出来。



下面的脚本(写在命令行上)读取整个文件并形成一行数组。然后它会遍历它并为每个匹配打印周围的两行,或者直到数组的开始/结束。

  perl -MList :: Util = min,max -0777 -wnE'
@m = split / \ n /; ($ .. $#m){
if($ m [$ _] =〜/ exception /){
$ bi = max(0,$ _-2);

$ ei = min($ _ + 2,$#m);
表示@m [$ bi .. $ ei];
表示---
}
}
'input.txt

打印 --- 以便于查看输出。这将打印所需的输出。



-0777 选项使它成为 slurp 整个文件放入 $ _ 变量中,该变量是换行符拆分。迭代遍历数组索引( $#m @m 的最后一个元素的索引)。 $ bi $ ei 是要打印的开始/结束索引,在开始时不能为+/- 2和数组的结尾。

输出可以通过管道传输到 tail ,但这不能自动化:if最后两行中的匹配会有(一两个)较少的输出行,因此输入需要知道精确的截止点。或者在脚本中找到匹配的索引,对于0 .. $#m; ,使用 @idx = grep {$ m [$ _] =〜/ exception /},并使用在这种情况下,只打印最后两个。



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

保持逐行处理会使工作变得更加复杂。我们需要跟踪匹配情况,以便我们在阅读完后可以打印以下内容。但是在这里我们需要多个这样的记录 - 对于下一个匹配(es)以及它们,如果它们在下面的行中进行打印。


I have a file like:

exception: anythinggggg...
exception: anythinggggg...
abchdhjsdhsd
ygsuhesnkc
exception: anythingggg...
exception: anything...
..
..

I want to grep the latest 2 occurrences of exception keyword along with 3 lines before and 3 lines after it.

I am using something like

grep -C 3 exception | tail -12

I am using tail -12 here as I want 6 lines per occurrence and latest 2 occurrences. this works fine when occurrences of exception are far off from each other but gives me useless lines if say both occurrences are consecutive.

abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
abdgjsd
exception
exception
exception
abcd

In the above case, it gives me

abdgjsd
abdgjsd
abdgjsd
exception
exception
exception
abcd

however, what I want is

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

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

Is there another way to this? Probably something in whch I can also specify the number of occurrences and not just grep lines and tail some output from it.

解决方案

The output you get is because grep stops printing context (-C) at the next match. I don't see how to make it behave otherwise.

The script below (written on the command-line) reads the whole file and forms an array of lines. Then it goes through it and prints surrounding two lines for each match, or up to start/end of array.

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

The --- are printed for easier reviewing of output. This prints the desired output.

The -0777 option makes it slurp the whole file into the $_ variable, which is split by newline. The iteration goes over the array index ($#m is the index of the last element of @m). The $bi and $ei are begin/end index to print, which cannot be +/- 2 near the beginning and end of the array.

The output can be piped to tail but this can't be automated: if a match is within the last two lines there'll be (one or two) fewer lines of output so input need be known for precise cut-off. Or find indices of matches in the script, @idx = grep { $m[$_] =~ /exception/} for 0..$#m;, and use that in the condition to only print the last two.

If you are going to use something like this I'd make it a script. Then read all lines into an array directly, provide command-line options (like -C in grep), etc.

Maintaining line-by-line processing would make the job far more complicated. We need to keep track of a match so that we can print the following lines once we read them. But here we need multiple such records -- for the next match(es) as well, if they come within the following lines to be printed.

这篇关于grep 3最新发生的事件和一些线路发生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆