grep
并且sed
默认情况下都被描述为使用“基本正则表达式”(“BRE”)。BRE在这里有很好的描述。
但是考虑这个输出:
# echo ' aaaaa ' | grep '\(aaaaa\|bbbbb\)'
aaaaa
# echo ' aaaaa ' | sed '/\(aaaaa\|bbbbb\)/ s/ /_/g'
aaaaa
在第一个命令中,\( ... \| ... \)
语法显然是,(X OR Y)
因为输出通过了grep
。
在第二个命令中,\( ... \| ... \)
语法显然没有充当,(X OR Y)
因为空格没有更改为下划线。
(相比之下,两个命令都被识别\+
为“一个或多个重复”)
发生了什么事?为什么在 FreeBSD 中似乎有两种 BRE,其中一种可以识别另一种不能识别的语法?
更深层次的问题是,许多项目着眼于 BRE 以提供对其他类 unix 系统的可移植性。但这表明即使 BRE 在各个平台之间也不可能相同,即使它们在各个平台中都不相同。啊?
链接文章中的描述是错误的。
实际的 POSIX 定义指出:
普通字符被定义为除 BRE 特殊字符
.[^$*
和反斜杠本身之外的任何字符。因此,与该页面声称的不同,
\+
BRE 中未定义 ,\|
.一些正则表达式实现将它们定义为与 ERE 相同
+
,|
但尤其是 GNU 的。但是您不应该指望这一点,而是坚持定义的功能。当然,这里的问题是
|
BRE 中根本不存在 ERE 交替运算符,而 ERE 的等价物+
非常丑陋(它是\{1,\}
)。因此,您可能想改用 ERE。or
不是 BRE(基本正则表达式)。您需要指定-E
扩展BRE。请参阅GNU 或 BSD Sed 中的正则表达式交替/或运算符 (foo|bar)
更新
为什么 grep 有效?
我们可以用grep选择我们想要使用什么样的模式
通过使用这些开关,我们可以看到
grep
确实默认为 BRE,并且 OP 表达式因 ERE 而失败:grep和sed都参考了 re_format (7),其中明确指出:
但似乎如果我们“逃离管道”,那么我们确实获得了功能。那肯定有味道。此外,该球场似乎最近出现了破损 - 请参阅regex(3): Add test to cover recent BRE regression。
似乎有一些工作可以替换libc 中的正则表达式。
正如查尔斯·达菲(Charles Duffy)在下面评论
我习惯了使用 FreeBSD 的非常好的文档。这意味着我不确定这是否是有意的但没有记录在案 - 或破损。