如何使用sed打印两个图案之间的线条

如何使用sed打印两个图案之间的线条,sed,awk,Sed,Awk,如何打印图案1和图案2之间的线条,但我不需要图案1和图案3之间的线条 请在sed、awk中建议解决方案 我有这样的案子 pattern1 blah blah blah blah blah blah blah blah blah pattern2 pattern1 blah blah blah blah blah blah pattern3 pattern1 blah blah blah blah blah blah pattern2 pattern1 blah blah blah blah b

如何打印图案1和图案2之间的线条,但我不需要图案1和图案3之间的线条

请在sed、awk中建议解决方案

我有这样的案子

pattern1
blah blah blah
blah blah blah
blah blah blah
pattern2
pattern1
blah blah blah
blah blah blah
pattern3
pattern1
blah blah blah
blah blah blah
pattern2
pattern1
blah blah blah 
blah blah blah
pattern3
期望输出:

pattern1
blah blah blah
blah blah blah
blah blah blah
pattern2
pattern1
blah blah blah
blah blah blah
pattern2

我迷失在纯粹的sed解决方案中的等待空间中;因此,这里有一个替代方案

$ tac input | sed '/pattern3/,/pattern1/d' | tac
pattern1
blah blah blah
blah blah blah
blah blah blah
pattern2
pattern1
blah blah blah
blah blah blah
pattern2
一种方法:

$ awk '/pattern1/{s=1;f=1;s=NR}f{p[NR]=$0}/pattern3/{s=0}/pattern2/&&s{f=0;for(i=s;i<=NR;i++)print p[i]}' file
pattern1
blah blah blah
blah blah blah
blah blah blah
pattern2
pattern1
blah blah blah
blah blah blah
pattern2
$awk'/pattern1/{s=1;f=1;s=NR}f{p[NR]=$0}/pattern3/{s=0}/pattern2/&s{f=0;for(i=s;i)
为了有助于理解,下面是上面几行内容,其中包含了更为详细的变量名:

awk '
/pattern1/ {
    found=!found
    buffer=""
}

found {
    buffer = buffer $0 ORS
}

/pattern2/ {
    if (found) {
        printf "%s",buffer
    }
    found=0
}

/pattern3/ {
    found=0
}
' file
对于sed:

sed -n '/pattern1/{:l N;/pattern3/b;/pattern2/!bl;p}' input
说明

/pattern1/{   # Match pattern1 and ...
:l N;         # start loop and read a line
/pattern3/b   # quit if pattern3 matches
/pattern2/!bl # loop until pattern2 matches
 p            # print all lines
输出

pattern1
blah blah blah
blah blah blah
blah blah blah
pattern2
pattern1
blah blah blah
blah blah blah
pattern2

+1这比我最初想象的要复杂;我仍在为我的sed而挣扎:-)@FredrikPihl-这不是一个简单的单行替换,因此自20世纪70年代中期awk发明以来,这就不是sed的合适任务。@EdMorton-你似乎真的对sed怀恨在心:-)@FredrikPihl-不,sed很好,我几乎每天都在使用它。不幸的是,人们仍然试图完整地使用它非常不恰当的方式,让新来者对脚本感到困惑,给sed起了一个不好的名字,因为晦涩难懂的脚本。如果我们能摆脱所有那些神秘的sed语言结构,并将其精简为4或5个有用的结构,那么OP对此不是100%清楚,但这将从
pattern1
打印到
pattern3
对于
pattern3
位于
pattern1
pattern2
+1之间的情况,我与您发布的解决方案斗争了很长一段时间;出于某些愚蠢的原因,我在
/pattern3/
部分中使用了
d
而不是
b
,无法理解为什么它不起作用…@sudo\u-它的简短,而不是con简洁。简洁是简洁和清晰的结合。简洁是软件中令人向往的品质,简洁不是。@EdMorton,清晰不是sed的强项:)@EdMorton,我同意。但我也认为这种简单的循环和
N
结构是可以的,尽管理解力有限。还有
awk
脚本在我看来总是很难看。@perreal-与sed不同,你可以用任何你喜欢的风格编写awk脚本,就像用任何其他编程语言一样。因此,如果你发现有一种风格难看,就不要用那种风格编写代码。sed解决方案的问题不仅仅是简单的不可理解性,而是最微小的、概念上最简单的需求会发生变化(例如,如果pattern1->pattern2记录包含单词“foo”,则不要打印该记录)将意味着完全重新编写脚本,或者如果不添加管道和更多工具,这是不可能的。+1:我认为这是这里列出的最简单、最清晰的解决方案。@EdMorton:如果你给我看你的,我会给你看我的。你会如何调整代码,将输入翻译成法语?(当然,AWK是一种比sed更强大、更强大的语言。这似乎不是反对简单的sed脚本的理由——特别是当您没有简单的AWK脚本时。)@ruaka这看起来最清楚的原因是因为它与其他3个答案做的事情不同,这个答案有缺陷,请参阅我的第一条评论。@ruakh-我已经发布了一个简单的awk脚本。它找到开始模式并设置标志,初始化缓冲区。当设置标志时,它会将当前行添加到缓冲区。如果/当它找到时这是一种结束模式,它会在必要时打印缓冲区并清除标志。非常简单,并且可以轻松扩展到任何实际的潜在需求更改(不包括翻译成法语).@ruakh既不
tac-input | sed'/pattern3/,/pattern1/d'| tac
也不
tac-input | sed-n'/pattern2/,/pattern1/p'/tac
工作,因为它们都会失败(但方式不同)当pattern2出现在pattern1->pattern3块之后,但在随后的pattern1之前时,让我们通过查看在给定(IMHO很可能)输入的情况下有效的sed和awk解决方案来比较苹果。
pattern1
blah blah blah
blah blah blah
blah blah blah
pattern2
pattern1
blah blah blah
blah blah blah
pattern2