我有一个要求。 比方说,我在文件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速度较慢。
答案 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 -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