【问题标题】:How to search groups of 3 lines with a certain pattern?如何搜索具有特定模式的 3 行组?
【发布时间】:2015-09-23 14:26:02
【问题描述】:

我想要做的只是在以下文件中搜索并打印 3 个连续行的组:

C30                1.86494717          7.48500210          9.88662475
O86                1.23405589          6.84423578         21.24967645
O88                5.28196032          8.12576842         21.24967645
O90                3.01950053          8.12576842          3.03566806
C32                8.01630633          7.48500210         15.95796089
O92                1.07505084          8.12576842          9.10700419
O94                7.22641001          8.12576842         15.17834032
O96                6.07185664          6.20346947         22.02929701
xxx                xxxxxxxxxx          xxxxxxxxxx         xxxxxxxxxxx
O111               3.82376560          6.83952632         25.21182108
H29                3.45376598          7.57952642         25.95182118
H30                4.93376561          6.83952632         25.21182108
O112               2.46658853          6.91893543         28.05848681
H31                2.09658891          7.65893553         28.79848692
H32                3.57658854          6.91893543         28.05848681
O113               6.25457469          6.74244996         26.28735053
H33                5.88457507          7.48245006         27.02735064
H34                7.36457470          6.74244996         26.28735053

我想在这种情况下找到遵循这种模式“O”“H”“H”的行:

    Ox               
    Hx  
    Hx

我用grep 尝试了一些东西,但它不能正常工作。

有什么建议吗?

非常感谢。

【问题讨论】:

    标签: bash shell sed grep


    【解决方案1】:

    如果我明白你想要什么,这个 sed 应该可以工作

    sed '/^O/{N;/\nH/{N;/\nH[^\n]*$/p}};d' file
    
    O111               3.82376560          6.83952632         25.21182108
    H29                3.45376598          7.57952642         25.95182118
    H30                4.93376561          6.83952632         25.21182108
    O112               2.46658853          6.91893543         28.05848681
    H31                2.09658891          7.65893553         28.79848692
    H32                3.57658854          6.91893543         28.05848681
    O113               6.25457469          6.74244996         26.28735053
    H33                5.88457507          7.48245006         27.02735064
    H34                7.36457470          6.74244996         26.28735053
    

    编辑

    如果两个O 行的倍数在一起,我搞砸了上面的内容。

    虽然会更长一些,但下面会...

    sed '/^O/{:1;N;/\nH/{N;/\nH[^\n]*$/p};/\nO[^\n]*/{s/.*\n//;b1}};d' file
    

    【讨论】:

    • @git 如果说有三行Os而不是两行,它会起作用,只用两行O然后HH试试
    • 没关系,对我来说工作,这就是我所需要的。非常感谢。
    • 你好,你知道什么可以选择逆,我的意思是除了这 3 行模式之外的所有...
    • @git 有点晚了,不过把p换成d,最后去掉d就行了。
    【解决方案2】:

    使用较新版本的 GNU grep 具有 -z 选项来匹配多行输入:

    $ grep -Pzo 'O[^\n]+\nH[^\n]+\nH[^\n]+' file.txt
    O111               3.82376560          6.83952632         25.21182108
    H29                3.45376598          7.57952642         25.95182118
    H30                4.93376561          6.83952632         25.21182108
    O112               2.46658853          6.91893543         28.05848681
    H31                2.09658891          7.65893553         28.79848692
    H32                3.57658854          6.91893543         28.05848681
    O113               6.25457469          6.74244996         26.28735053
    H33                5.88457507          7.48245006         27.02735064
    H34                7.36457470          6.74244996         26.28735053
    

    您还可以使用pcregrep-M 选项来匹配多行输入:

    $ pcregrep -M 'O[^\n]+\nH[^\n]+\nH[^\n]+' file.txt 
    O111               3.82376560          6.83952632         25.21182108
    H29                3.45376598          7.57952642         25.95182118
    H30                4.93376561          6.83952632         25.21182108
    O112               2.46658853          6.91893543         28.05848681
    H31                2.09658891          7.65893553         28.79848692
    H32                3.57658854          6.91893543         28.05848681
    O113               6.25457469          6.74244996         26.28735053
    H33                5.88457507          7.48245006         27.02735064
    H34                7.36457470          6.74244996         26.28735053
    

    【讨论】:

    • [^ ]+ 的目的是什么?
    • 但是你匹配的是它之前的换行符,所以它显然必须是第一列。
    • @999999999999999999999999999999如果我们认为所有的行都像 OP 提到的那样,是的,那会做..edited..
    • @heemayl 您如何设法选择逆向(我的意思是选择除这 3 行之外的所有行)。你有什么主意吗?类似于 grep 中的 -v。
    • @git 这需要不同的方法..-v 不起作用,因为我们将多行匹配在一起,而 -v 在我们处理单行时起作用..
    【解决方案3】:

    gawk -vRS='(^|\n)O[^\n]*\nH[^\n]*\nH[^\n]*' '{print RT}'

    ^ 匹配文件的开头,而不是任何行的开头(这可能是一个暗角)。
    RT 是匹配 RS 的文本。
    为此,您需要 GNU Awk;标准 awk 不允许正则表达式记录分隔符。

    【讨论】:

      【解决方案4】:

      你可以使用这个awk

      awk '/^O/ { oline=NR; a=$0; next }
           /^H/ && oline && NR==(oline+1) { hline=NR; a=a RS $0; next }
           /^H/ && hline && NR==(hline+1) {
             print a ORS $0;
             aline=hline=0
      }' file
      
      O111               3.82376560          6.83952632         25.21182108
      H29                3.45376598          7.57952642         25.95182118
      H30                4.93376561          6.83952632         25.21182108
      O112               2.46658853          6.91893543         28.05848681
      H31                2.09658891          7.65893553         28.79848692
      H32                3.57658854          6.91893543         28.05848681
      O113               6.25457469          6.74244996         26.28735053
      H33                5.88457507          7.48245006         27.02735064
      H34                7.36457470          6.74244996         26.28735053
      

      【讨论】:

        【解决方案5】:
        awk '
        { k = substr($0,1,1) }
        (k=="H") && (prevNR["H"]==(NR-1)) && (prevNR["O"]==(NR-2)) {
            print prevRec["O"] ORS prevRec["H"] ORS $0
        }
        { prevNR[k]=NR; prevRec[k]=$0 }
        ' file
        O111               3.82376560          6.83952632         25.21182108
        H29                3.45376598          7.57952642         25.95182118
        H30                4.93376561          6.83952632         25.21182108
        O112               2.46658853          6.91893543         28.05848681
        H31                2.09658891          7.65893553         28.79848692
        H32                3.57658854          6.91893543         28.05848681
        O113               6.25457469          6.74244996         26.28735053
        H33                5.88457507          7.48245006         27.02735064
        H34                7.36457470          6.74244996         26.28735053
        

        【讨论】:

          猜你喜欢
          • 2017-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-23
          • 1970-01-01
          • 1970-01-01
          • 2014-05-03
          相关资源
          最近更新 更多