Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何搜索具有特定模式的3行分组?_Bash_Shell_Sed_Grep - Fatal编程技术网

Bash 如何搜索具有特定模式的3行分组?

Bash 如何搜索具有特定模式的3行分组?,bash,shell,sed,grep,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行连续的组:

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”的行:

我用
grep
尝试了一些东西,但没有正常工作

有什么建议吗


非常感谢。

使用新版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 '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
选项来匹配多行输入:

$ 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 '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应该可以工作

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

您可以使用此
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
gawk-vRS='(^\n)O[^\n]*\nH[^\n]*\nH[^\n]*''{print RT}'

^
匹配文件的开头,而不是任何行的开头(这可能是一个暗角)。
RT
是与
RS
匹配的文本

为此,您需要GNU Awk;标准Awk不允许使用正则表达式记录分隔符。

使用
[^]+
的目的是什么?但是您要匹配它前面的换行符,因此它显然必须是第一列@999999999999999999999999999999如果我们认为所有的线条都会像OP所提到的那样,那么是的……编辑…@ HeMayl你如何选择逆(我的意思是选择除了这3行以外的所有)。你知道吗?类似于grep中的-v。@git需要一种不同的方法。
-v
不起作用,因为我们在一起匹配多行,而
-v
在处理单行时起作用。@git如果说有三行操作系统,而不是两行操作系统,那么就用两行操作系统试试,hh就没关系了,对我来说,工作就是我所需要的一切。非常感谢。再次您好,您知道如何选择反转,我的意思是除了这三行模式以外的所有模式…@git有点晚了,但只需将
p
切换到
d
,并删除最后的
d
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