POSIX sed对于地址范围从已删除的行开始的“ 1d; 1,2d”有什么要求?
在对这个问题的评论中,出现了一个案例,其中各种sed实现在一个相当简单的程序上存在分歧,而我们(或至少我)无法确定规范对它的实际要求。 问题是从删除行开始的范围的行为: 1d;1,2d 即使在到达该命令之前删除了范围的开头,也应该删除第2行吗?我最初的期望是与BSD sed一致,“否”,而GNU sed说“是”,并且检查规范文本并不能完全解决问题。 符合我期望的是(至少)macOS和Solaris sed以及BSD sed。(至少)GNU和Busybox意见不同sed,这里有很多人。前两个通过SUS认证,而其他两个可能更广泛。哪种行为是正确的? 两个地址范围的规范文本显示: 然后,sed实用程序应按顺序应用其地址选择该模式空间的所有命令,直到命令开始下一个周期或退出为止。 和 具有两个地址的编辑命令应从与第一个地址匹配的第一个模式空间到与第二个地址匹配的下一个模式空间选择包含范围。[...]从选定范围后的第一行开始,sed将再次寻找第一个地址。此后,应重复该过程。 可以说,第2行是 内,不管开始点是否已删除“从通过相匹配的第二下一图案空间匹配的第一个地址中的第一图案空间包容范围”。另一方面,我希望第一个d继续进行下一个周期,而不给该范围一个开始的机会。UNIX™认证的实现可以实现我期望的功能,但可能不会达到规范的要求。 一些说明性的实验遵循,但关键的问题是:什么应该 sed在范围上已删除的行开始呢? 实验与范例 这个问题的简化展示是,它打印行的额外副本而不是删除它们: printf 'a\nb\n' | sed -e '1d;1,2p' 这提供sed了两行输入,a和b。该程序执行两件事: 用删除第一行1d。该d命令将 删除模式空间并开始下一个循环。和 从1到2中选择行范围,并明确打印出来,除了自动打印每行接收到的内容。因此,该范围内的一行应出现两次。 我的期望是应该打印 b 仅,由于不应用该范围,因为1,2在第1行期间从未达到该范围(因为已经d跳至下一个循环/行),因此范围内的包含从未被开始,a而已被删除。通常,sed与macOS和Solaris 10 兼容的Unix会产生此输出,与sedSolaris和BSD sed中的非POSIX一样。 另一方面,GNU sed打印 b b 表示它已经解释了范围。这在POSIX模式下都不会发生。Busybox的sed具有相同的行为(但并非总是相同的行为,因此它似乎不是共享代码的结果)。 进一步的实验 printf 'a\nb\nc\nd\ne\n' | sed -e '2d;2,/c/p' printf 'a\nb\nc\nd\ne\n' | …