如何使用特定模式搜索3行组?

时间:2015-09-23 14:26:02

标签: bash shell sed grep

我想要做的只是在以下文件中搜索并打印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,但它无法正常工作。

有什么建议吗?

非常感谢提前。

5 个答案:

答案 0 :(得分:4)

如果我理解你想要的东西,这个sed应该可以工作

$ 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

修改

如果有两条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

答案 1 :(得分:3)

使用具有grep选项的较新版本的GNU -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

您还可以使用-M的{​​{1}}选项来匹配多行输入:

pcregrep

答案 2 :(得分:3)

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

^匹配文件的开头,而不是任何行的开头(这可能是一个黑暗的角落)。
RT是与RS匹配的文字 你需要GNU Awk;标准Awk不允许使用正则表达式记录分隔符。

答案 3 :(得分:2)

您可以使用此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

答案 4 :(得分:2)

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