找到两个匹配,中间有'n`行

时间:2013-07-02 03:48:45

标签: linux awk grep

在我的Linux终端中,我需要查找此类事件的发生次数,其中pattern 1pattern 2出现在两行中,这两行正好相距n行,并附加要求pattern 3行无法显示n行。 例如,如果我有一个文本文件

...
a
* pat1 **
b
c
** pat2 ****
* pat1 **
b
** pat2 ****
*******pat1**
efda
*pat3****
**pat2********
...

n=2pattern 1pat1时,pattern 2pat2pattern 3pat3,则有只发生一次。

如何在awkgrep(或其姐妹)等实用工具中方便地执行此操作。我知道如何使用python或perl来执行此操作,但只是想知道这些实用工具是否可以做同样的事。

谢谢。

这是我在阅读@ Barmar的回答后尝试的内容

awk -v n=2 '/pat1/ { first = NR } 
           !/pat3/ 
            /pat2/ && first && NR - first == n { count++ } END {print count}'

但我仍然没有正确理解。我需要在四种情况下执行此操作:

  • pat1pat3是相同的。
  • pat2pat3相同。
  • 所有这三种模式都是一样的。
  • 其中没有两个是相同的。

2 个答案:

答案 0 :(得分:2)

awk -v n=2 '/pat1/ { first = NR }
            /pat2/ && first && NR - first == n { count++ }
            END {print count}'

以下是具有额外pat3要求的代码:

awk -v n=2 '/pat3/ && first { pat3 = 1; first = 0 }
            /pat1/ && !pat3 { first = NR }
            /pat2/ && first && NR - first == n { count++; first = 0 }
            END {print count}'

我认为这将适用于所有模式组合相同,但我还没有测试过。当模式可以相同时,这个技巧的作用是在脚本中匹配一个测试的行不会阻止它通过剩余的测试。因此,脚本必须重置状态变量pat3first,以避免将同一行视为pat1pat3匹配。

在你的尝试中,行

!/pat3/

什么都不做。首先,它在语法上并不正确 - 每个测试都需要后跟一个声明或块来说明匹配时要做什么。其次,即使你在它之后放一个空块,这只是意味着“如果当前行与pat3不匹配,则不要做任何事情”。它对脚本中其他模式匹配的行为没有任何影响。

我认为你需要找一个awk教程来学习awk的基本操作模型。我不打算在这里教你,这不是辅导网站。

答案 1 :(得分:1)

使用

sed -ne '/pat1/{N;N;/\([^\n]*\n\)\{2\}.*pat2/{/pat3/!p}}' input

一些解释:

if (pat1 matches) {                     #  /pat1/{
     read and append 2 lines            #  N;N;
     if (pat2 matches after 2 '\n's) {  #  /\([^\n]*\n\)\{2\}.*pat2/ {
          if (pat3 does not match) {    #  /pat3/!
             print                      #  p
          }                             
      }                                 #  }
 }                                      #  }