sed n似乎没有像我想象的那样工作

时间:2015-11-24 21:01:20

标签: sed

我试图复制我在此处找到的示例: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 /命令并处理它。

实际上,它似乎以某种方式导致范围的结束被遗漏。有人会解释发生了什么吗?

3 个答案:

答案 0 :(得分:1)

应该是:

/^begin$/,/^end$/{
    /^begin$\|^end$/!d
}

为什么你的命令错了?

那里的n命令错了。在第二个例子中,它将:

  1. begin ---> n读下一行(重要:这不会影响范围地址的状态(开始,结束))

    1a上。 end ---> /end/!不适用。请勿删除

  2. 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/!)开头。

另见:sed or awk: delete n lines following a pattern