考虑输入:
=sec1=
some-line
some-other-line
foo
bar=baz
=sec2=
c=baz
例如,如果我只想处理= sec 1 =,我可以通过以下方式注解掉该部分:
sed -e '/=sec1=/,/=[a-z]*=/s:^:#:' < input
差不多了
这将注解行 *,包括 *“= sec 1 =”和“= sec 2 =”行,结果如下:
#=sec1=
#some-line
#some-other-line
#
#foo
#bar=baz
#
#=sec2=
c=baz
我的问题是:在sed中,从/START/,/END/范围中排除起始行和结束行的最简单方法是什么?
我知道在很多情况下,“s:“claws的细化可以在这个特定的情况下给出给予解决方案,但我在这里追求的是通用的解决方案。
在“塞德-一个介绍和介绍”布鲁斯巴内特写道:“我稍后将向您展示如何限制命令,但不包括包含指定模式的行。",但我无法找到他实际显示这一点的地方。
在Eric Pement编译的“USEFUL ONE-LINE SCRIPTS FOR SED“中,我只能找到包含的例子:
# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p' # case sensitive
6条答案
按热度按时间mitkmikd1#
这应该可以解决问题:
这将在sec1和sec2之间进行匹配,然后使用
b
命令跳过第一行和最后一行。这将在sec1和sec2之间留下所需的行(不含),s
命令将添加注解符号。不幸的是,您确实需要重复正则表达式来匹配分隔符。据我所知,没有更好的办法了。至少你可以保持正则表达式干净,即使它们被使用了两次。
这是改编自SED FAQ:如何对RE1和RE2之间的所有线路进行寻址,不包括线路本身?
2izufjch2#
如果你对范围之外的行不感兴趣,而只是想从问题中得到爱荷华州/蒙大拿州示例的非包含变体(这就是我来到这里的原因),你可以用第二个sed很容易地编写“except for the first and last matching lines”子句:
sed -n '/PATTERN1/,/PATTERN2/p' < input | sed '1d;$d'
就我个人而言,我觉得这比同等的方法稍微清楚一些(尽管在大文件上慢一些
sed -n '1,/PATTERN1/d;/PATTERN2/q;p' < input
n7taea2i3#
另一种方式是
/begin/n
->跳过具有“开始”模式的行/end/ !p
->打印所有没有“结束”模式的行摘自布鲁斯巴内特的sed教程http://www.grymoire.com/Unix/Sed.html#toc-uh-35a
drkbr07n4#
我用过:
这将搜索模式之间的所有行,然后打印不包含模式的所有内容
gr8qqesn5#
也可以使用awk
p8h8hvxi6#
你不需要重复任何正则表达式就可以做到这一点。
输出将为:
拆开sed脚本,我们有:
/^=sec1=$/
匹配开头部分标记的正则表达式地址{:0;n;/^=\w*=$/!{s/^/#/;b0}}
命令块,如下所示::0
稍后返回的标签n
打印当前行,并读取下一行/^=\w*=$/!
正则表达式地址匹配任何不是节标记的行{s/^/#/;b0}
命令块,如下所示:s/^/#/
将#
前置到该行b0
分支到标签0
:0
和b0
之间的内部循环将继续循环,直到遇到任何作为节标记(或文件结尾)的行。