不包括来自sed / START /的第一行和最后一行,/ END /

考虑input:

=sec1= some-line some-other-line foo bar=baz =sec2= c=baz 

如果我只想处理= sec1 =例如我可以通过以下方式注释该部分:

 sed -e '/=sec1=/,/=[az]*=/s:^:#:' < input 

差不多,差不多

这会对包括 “= sec1 =”和“= sec2 =”行的行进行注释,结果如下所示:

 #=sec1= #some-line #some-other-line # #foo #bar=baz # #=sec2= c=baz 

我的问题是: 什么是最简单的方法来排除开始和结束行从/ START /,/结束/范围在SED

我知道在很多情况下,“s :::”爪子的细化可以在这个特定情况下给出解决scheme,但是我在这里是通用解决scheme。

在“ Sed – 一个介绍和教程 ”中,Bruce Barnett写道:“稍后我会告诉你如何限制一个命令,但不包括含有指定模式的行。”但是我没有find他真正显示的地方这个。

在“ 用于SED的有用的单行脚本 ”由Eric Pement编写的时候,我只能find一个包容性的例子:

 # print section of file between two regular expressions (inclusive) sed -n '/Iowa/,/Montana/p' # case sensitive 

这应该做的伎俩:

 sed -e '/=sec1=/,/=sec2=/ { /=sec1=/b; /=sec2=/b; s/^/#/ }' < input 

这包含在sec1和sec2之间,然后用b命令跳过第一行和最后一行。 这会在sec1和sec2(独占)之间留下所需的行,并且s命令会添加注释符号。

不幸的是,你需要重复匹配分隔符的正则expression式。 据我所知,没有更好的方法来做到这一点。 至less你可以保持正则expression式的清洁,即使它们被使用了两次。

这是从SED FAQ改编而来:我如何处理RE1和RE2之间的所有线路,不包括线路本身?

如果你对这个范围之外的线条不感兴趣,但是只是想从这个问题(这是什么使我在这里)的问题中得到爱荷华州/蒙大拿州的非包含性的例子,你可以写下“除了第一个和最后一个匹配行“条款足够容易与第二个sed:

sed -n '/PATTERN1/,/PATTERN2/p' < input | sed '1d;$d'

就我个人而言,我发现这个比稍微更清晰(尽pipe在大文件上比较慢)

sed -n '1,/PATTERN1/d;/PATTERN2/q;p' < input

另一种方法是

 sed '/begin/,/end/ { /begin/n /end/ !p }' 

/begin/n – >跳过具有“begin”模式的行
/end/ !p – >打印所有没有“结束”模式的行

采取从布鲁斯·巴内特的sed教程http://www.grymoire.com/Unix/Sed.html#toc-uh-35a

你也可以使用awk

 awk '/sec1/{f=1;print;next}f && !/sec2/{ $0="#"$0}/sec2/{f=0}1' file 

我用过:

 sed '/begin/,/end/{/begin\|end/!p}' 

这将search模式之间的所有线,然后打印不包含模式的所有内容