我试图复制我在此处找到的示例:http://www.grymoire.com/Unix/Sed.html#uh-35a
这里是sed模式
/^begin$/,/^end$/{
/begin/n
/end/!d
}
这是第一个文件
begin
one
end
last line
这是第二个
begin
end
last line
当我在第一个文件上运行sed时,它删除了begin / end之间的内容,而且一切都很好。当我在第二次运行它时,它似乎错过了“结束”并删除了文件的其余部分。
在第一个文件上运行
$ sed -f x.sed a
begin
end
last line
在第二个
上运行$ sed -f x.sed b
begin
end
注意第二次运行时“最后一行”是如何丢失的。
我认为“n”会打印当前模式并吸入下一个模式。然后它会命中/ end /命令并处理它。
实际上,它似乎以某种方式导致范围的结束被遗漏。有人会解释发生了什么吗?
答案 0 :(得分:1)
应该是:
/^begin$/,/^end$/{
/^begin$\|^end$/!d
}
为什么你的命令错了?
那里的n
命令错了。在第二个例子中,它将:
begin
---> n读下一行(重要:这不会影响范围地址的状态(开始,结束))
1a上。 end
---> /end/!
不适用。请勿删除
last line
---> /end/!
适用。删除该行。 (sed
仍在搜索包含end
的行,因为n
命令跳过了该行)
答案 1 :(得分:0)
在@ hek2mgl的帮助下找到了另一种方法。我可以在第二个语句周围添加一个分支。我实际上需要这个,因为我想看到开始标签。所以你也可以这样做:
/^begin$/,/^end$/{
/begin/{ b skip }
/end/!d
:skip
}
答案 2 :(得分:0)
我认为你接近于让它做你想做的事。如果您想在匹配后删除下一行,则只需使用sed n
将其拉入,然后使用删除d
点击它。
看起来你想跳过以begin
开头的行之后的行,除非它end
并打印所有其他行。
如果是这样,以下内容就足够了:
/^begin$/,/^end$/{
/begin/{n;/end/!d}
}
它的工作原理是跳过开始后的下一行,除非它以end(/end/!
)开头。