搜索与字符串1匹配的多行不匹配的字符串2的文本

时间:2016-11-28 08:37:00

标签: regex awk sed grep

我的文件看起来像这样:

abc|100|test|line|with|multiple|information|||in|different||fields
abc|100|another|test|line|with|multiple|information|in||different|fields|
abc|110|different|looking|line|with|some|supplementary|information
abc|100|test|line|with|multiple|information|||in|different||fields
abc|110|different|looking|line|with|some|other|supplementary|information
abc|110|different|looking|line|with|additional||information
abc|100|another|test|line|with|multiple|information|in||different|fields|
abc|110|different|looking|line|with|supplementary|information

我正在寻找一个与sed / awk /(e)grep一起使用的正则表达式(它对我来说实际上对我来说无关紧要)在上面找到以下内容提到的文字:

abc|100|test|line|with|multiple|information|||in|different||fields
abc|110|different|looking|line|with|some|other|supplementary|information
abc|110|different|looking|line|with|additional||information

我想找回| 100 |如果后面跟着至少两个| 110 |在另一个之前的行| 100 |出现了一行。结果应该包含初始| 100 |与所有| 110 |一起排队后面的行但不是以下的| 100 |线。

sed -ne '/|100|/,/|110|/p'

为我提供了所有| 100 |的列表后面跟着至少一个| 110 |的行线。但它不检查,如果| 110 |线已多次重复。我得到了我不想找的结果。

sed -ne '/|100|/,/|100|/p'

返回所有| 100 |的列表行和下一个| 100 |之间的内容行包括下一个| 100 |线。

试图在搜索模式之间找到线条对我来说总是一场噩梦。我花了几个小时的尝试和错误来解决最终有效的类似问题。但我从来没有真正理解为什么。希望如此。这次可能会让我很头疼,也许可以解释这种模式是如何起作用的。我很确定,我会再次遇到这种问题,然后我终于可以帮助自己。

感谢您对此提供任何帮助!

此致

曼努埃尔

3 个答案:

答案 0 :(得分:0)

在AWK中,字段分隔符设置为管道字符,第二个字段与每行100和110进行比较。 $ 0表示输入文件中的一行。

BEGIN { FS = "|" }
{
    if($2 == 100) { 
        one_hundred = 1; 
        one_hundred_one = 0;
        var0 = $0
    } 

    if($2 == 110) { 
        one_hundred_one += 1; 
        if(one_hundred_one == 1 && one_hundred = 1) var1 = $0; 
        if(one_hundred_one == 2 && one_hundred = 1) var2 = $0;
    } 

    if(one_hundred == 1 && one_hundred_one == 2) {
        print var0
        print var1
        print var2
    }  
}

awk -f foo.awk input.txt

abc|100|test|line|with|multiple|information|||in|different||fields
abc|110|different|looking|line|with|some|other|supplementary|information
abc|110|different|looking|line|with|additional||information

答案 1 :(得分:0)

这是GNU awk的具体答案:使用|100|作为记录分隔符,|110|作为字段分隔符,并查找至少包含3个字段的记录。

gawk '
    BEGIN {
        # a newline, the first pipe-delimited column, then the "100" value
        RS="(\n[^|]+[|]100[|])"
        FS="[|]110[|]"
    } 
    NF >= 3 {print RT $0}        # RT is the actual text matching the RS pattern
' file

答案 2 :(得分:0)

我会在awk中这样做。

awk -F'|' '$2==100&&c>2{print b} $2==100{c=1;b=$0;next} $2==110&&c{c++;b=b RS $0;next} {c=0}' file

为便于阅读而破裂:

awk -F'|' '

  # If we're starting a new section and conditions have been met, print buffer
  $2==100 && c>2 {print b}

  # Start a section with a new count and a new buffer...
  $2==100 {c=1;b=$0;next}

  # Add to buffer
  $2==110 && c {c++;b=b RS $0}

  # Finally, zero everything if we encounter lines that don't fit the pattern
  {c=0;b=""}

' file

不是使用正则表达式,而是使用您指定的字段分隔符逐步执行该文件。在看到“开始”状态后,它开始保持缓冲区。随后的行与“继续”条件匹配,缓冲区会增长。一旦我们看到新部分的开始,如果计数器足够大,我们就打印缓冲区。

根据您的样本数据为我工作。