考虑sed
计划s/\(,\|$\)/-/g
。当在GNU sed
下运行各种输入时,它会提供以下似乎有点不一致的交互:
-
,
- > -
a
- > a-
a,
- > a-
,a
- > -a-
表达式的$
部分是否与行尾匹配似乎取决于最后一个匹配是否在行尾结束。我的直觉说g
标志应该从最后一次替换结束重复匹配,直到正则表达式无法匹配,在这种情况下,该程序应该总是向该行追加-
;但当然,我的直觉并不一定与POSIX规范相匹配。
阅读sed
的POSIX手册页,它说明了g
s
命令的,
标志:
全局替换BRE的所有非重叠实例,而不仅仅是第一个。如果同时指定了g和n,则结果未指定。
输入中的最后一个sed
是否重叠"与EOL或不相似似乎是开放的解释。还有什么可以澄清这个吗?这种行为是根据规范,还是GNU {{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
。我怀疑它可能比我假设的更多或更少。
在聊天中,我们还注意到:
sed
有-r
用于使用扩展正则表达式,但它们的行为似乎相似(当符号相应更改时)。sed
使用扩展正则表达式-E
。sed
似乎工作方式相似,因此这种行为似乎在sed
的多个实现中很常见。使用Mac OS X,我们遇到了意外的行为:
$ echo ",a" | sed -E 's/(,|$)/-/g'
-
$
在没有更好的假设的情况下,我们将其指定为“莫名其妙”或“可能(可能是?)马车”。 <{1}}没有明显的理由让人失踪。
使用Perl或Python可能是一个明智的选择。