sed全球替换应该如何在行尾?

时间:2016-05-15 02:24:09

标签: sed posix

考虑sed计划s/\(,\|$\)/-/g。当在GNU sed下运行各种输入时,它会提供以下似乎有点不一致的交互:

  • 空字符串 - > -
  • , - > -
  • a - > a-
  • a, - > a-
  • ,a - > -a-

表达式的$部分是否与行尾匹配似乎取决于最后一个匹配是否在行尾结束。我的直觉说g标志应该从最后一次替换结束重复匹配,直到正则表达式无法匹配,在这种情况下,该程序应该总是向该行追加-;但当然,我的直觉并不一定与POSIX规范相匹配。

阅读sed的POSIX手册页,它说明了g s命令的,标志:

  

全局替换BRE的所有非重叠实例,而不仅仅是第一个。如果同时指定了g和n,则结果未指定。

输入中的最后一个sed是否重叠"与EOL或不相似似乎是开放的解释。还有什么可以澄清这个吗?这种行为是根据规范,还是GNU {{1}}中的错误?

1 个答案:

答案 0 :(得分:1)

如评论中所述,然后在chat ...

中进行更广泛的讨论

你正在使用的符号(具体来说,\|表示替换)不是由POSIX sed指定的,所以不清楚是否有很多关于POSIX的说法任务。它部分地说:

  

sed实用程序应支持XBD Basic Regular Expressions中描述的BRE。

反过来说:

  

<backslash>'\\')前面的普通字符的解释未定义,除了:
  •字符')','(','{'和'}'   •数字1到9(包括匹配多个字符的BRE)
  •括号表达式中的字符。

这主要意味着您无法向POSIX寻求所需的行为。我认为替代方案是从左到右评估的,但$上下文发生在逗号之后。我简要地查看了你的清单,并没有看到令人惊讶的行为。线上的第一场比赛总是胜利,不是吗?

我不确定它究竟是如何工作的,但是我猜测换行符已被删除,然后在EOL之前对字符进行替换,扫描恢复但是处于EOL状态,所以它不会再做点什么了。

预计POSIX sed可能会根据POSIX regexec()等功能实现。您指出g - 修饰符的解释留给sed。我怀疑它可能比我假设的更多或更少。

在聊天中,我们还注意到:

  • GNU sed-r用于使用扩展正则表达式,但它们的行为似乎相似(当符号相应更改时)。
  • BSD和Mac OS X sed使用扩展正则表达式-E
  • Busybox sed似乎工作方式相似,因此这种行为似乎在sed的多个实现中很常见。
  • 使用Mac OS X,我们遇到了意外的行为:

    $ echo ",a" | sed -E 's/(,|$)/-/g'
    -
    $
    

    在没有更好的假设的情况下,我们将其指定为“莫名其妙”或“可能(可能是?)马车”。 <{1}}没有明显的理由让人失踪。

  • 使用Perl或Python可能是一个明智的选择。