考虑输入:
=sec1=
some-line
some-other-line
foo
bar=baz
=sec2=
c=baz
如果我只想处理= sec1 =我可以通过以下方式注释掉该部分:
sed -e '/=sec1=/,/=[a-z]*=/s:^:#:' < input
......好吧,差不多。
这将注释行包括“= sec1 =”和“= sec2 =”行,结果将类似于:
#=sec1=
#some-line
#some-other-line
#
#foo
#bar=baz
#
#=sec2=
c=baz
我的问题是:从sed中的/ START /,/ END /范围中排除开始和结束行的最简单方法是什么?
我知道在许多情况下,“s :::”爪子的细化可以在这个特定情况下给出解决方案,但我在这里是通用解决方案。
在“Sed - An Introduction and Tutorial”中,Bruce Barnett写道:“我稍后会告诉你如何限制命令,但不包括包含指定模式的行。”但我无法找到他在哪里实际上显示了这一点。
在Eric Pement编写的“USEFUL ONE-LINE SCRIPTS FOR SED”中,我只能找到包容性的例子:
# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p' # case sensitive
答案 0 :(得分:36)
这应该可以解决问题:
sed -e '/=sec1=/,/=sec2=/ { /=sec1=/b; /=sec2=/b; s/^/#/ }' < input
这包括sec1和sec2之间的匹配,然后使用b
命令跳过第一行和最后一行。这会在sec1和sec2之间留下所需的行(不包括),s
命令会添加注释符号。
不幸的是,您确实需要重复使用正则表达式来匹配分隔符。据我所知,没有比这更好的方法了。至少你可以保持regexp干净,即使它们被使用了两次。
这是根据SED FAQ: How do I address all the lines between RE1 and RE2, excluding the lines themselves?
改编的答案 1 :(得分:13)
如果你对范围之外的线路不感兴趣,但只是想从问题(这就是我带到这里)的爱荷华州/蒙大拿州的非包容性变体,你可以写“除了第一个和最后一个匹配的行“子句很容易与第二个sed:
sed -n '/PATTERN1/,/PATTERN2/p' < input | sed '1d;$d'
就我个人而言,我发现这比同等的
更清晰(尽管在大文件上比较慢) sed -n '1,/PATTERN1/d;/PATTERN2/q;p' < input
答案 2 :(得分:7)
另一种方式是
sed '/begin/,/end/ {
/begin/n
/end/ !p
}'
/begin/n
- &gt;跳过具有“开始”模式的行
/end/ !p
- &gt;打印所有没有“结束”模式的行
取自Bruce Barnett的sed教程http://www.grymoire.com/Unix/Sed.html#toc-uh-35a
答案 3 :(得分:1)
你也可以使用awk
awk '/sec1/{f=1;print;next}f && !/sec2/{ $0="#"$0}/sec2/{f=0}1' file
答案 4 :(得分:1)
我已经使用过:
sed '/begin/,/end/{/begin\|end/!p}'
这将搜索模式之间的所有行,然后打印不包含模式的所有行