Sti*_*lez 5 freebsd compatibility regular-expression portability
grep
并且sed
都被描述为默认使用“基本正则表达式”(“BRE”)。BRE在这里得到了很好的描述。
但考虑这个输出:
# echo ' aaaaa ' | grep '\(aaaaa\|bbbbb\)'
aaaaa
# echo ' aaaaa ' | sed '/\(aaaaa\|bbbbb\)/ s/ /_/g'
aaaaa
Run Code Online (Sandbox Code Playgroud)
在第一个命令中,\( ... \| ... \)
语法显然表现为(X OR Y)
,因为输出通过grep
。
在第二个命令中,\( ... \| ... \)
语法显然没有作为(X OR Y)
,因为空格没有更改为下划线。
(相比之下,这两个命令都识别\+
为“一次或多次重复”)
发生了什么事?为什么在 FreeBSD 中似乎有两种类型的 BRE,其中一种可以识别另一种不能识别的语法?
更深层次的问题是,许多项目都着眼于 BRE 来为其他类 Unix 系统提供可移植性。但这表明即使 BRE 也不太可能跨平台相同,如果它们在单个平台内甚至不能相同。啊?
链接文章中的描述是错误的。
实际的 POSIX 定义指出:
以未转义的 <backslash> ( '\' ) 开头的普通字符的解释未定义,除了[
(){}
、数字和括号表达式]
普通字符定义为除 BRE 特殊字符.[^$*
和反斜杠本身之外的任何字符。
因此,与该页面声明不同,\+
BRE 中的是未定义的,因此\|
.
一些正则表达式实现将它们定义为与 ERE 相同+
,|
但尤其是 GNU 实现。但是您不应该指望这一点,而是坚持定义的功能。
当然,这里的问题是 ERE 交替运算符|
在 BRE 中根本不存在,而 ERE 的等价物+
非常丑陋(它是\{1,\}
)。所以你可能想改用 ERE。