多线AWK捕获

时间:2014-09-18 08:08:13

标签: awk

我有一个要求。 比方说,我在文件file1.txt

中输入
start
asfsafsf
faffsa
gygfyt
end1
dddadd
start
afsaf
safsaf
asdasd
start
asda
DD
end2
aasfsa
afaf
start
dada
afaf
asfs
end3
fafaf

我需要在start和amp;之间捕获字符串end3,然后输出预期为,

start
dada
afaf
asfs
end3

如果我需要捕获end2,那么我需要输出as,

start
asda
DD
end2

有些人可以帮助我使用awk命令,因为sed速度较慢。

4 个答案:

答案 0 :(得分:1)

反转输入文件可以解决问题:

$ tac infile|awk '/end3/{f=1}f;/start/{f=0}'|tac

对于多个文件,请使用:

$ tac files*|awk '/end3/{f=1}f;/start/{f=0}'|tac

答案 1 :(得分:1)

你可以非常清晰地做到这一点:

awk '/start/{out=$0;next} /end3/{out=out RS $0;print out;out=""}{if(length(out))out=out RS $0}' file

因此,如果我们看到单词start,我们将输出字符串设置为当前行并移至下一行。如果我们已达到end3(您可以将其更改为end2),我们会打印累计输出。在所有其他行上,如果我们已经开始累积输出行,我们在换行符之后添加当前行。

如果你有很多文件并且想要并行解析它们,你可以使用GNU Parallel,如下所示:

parallel -q awk '/start/{out=$0;next} /end3/{out=out RS $0;print out;out=""}{if(length(out))out=out RS $0}' ::: *.txt

答案 2 :(得分:0)

无论start - endx是否配对

,这个awk oneliner都会这样做
awk -v n="2" 'NR==FNR{a[$0]=NR;if($0~"end"n){s=a["start"];e=a["end"n];nextfile}}
                      FNR>=s&&FNR<=e' file file

-v n="2"更改为变量以使其动态化。

答案 3 :(得分:0)

通过perl,

$ perl -0777pe 's/.*(?:^|\n)(start(?:(?!start|end3).)*\nend3)(?:\n|$).*/\1\n/s' f
start
dada
afaf
asfs
end3
$ perl -0777pe 's/.*(?:^|\n)(start(?:(?!start|end2).)*\nend2)(?:\n|$).*/\1\n/s' f
start
asda
DD
end2