bash 正则表达式不支持 \b 是否有原因?

bash 正则表达式不支持 \b 是否有原因?

据我所知,\bbash 不支持指示“单词边界”的元序列:

if [[ $foo =~ .*\bWORD\b.* ]]; then

有什么原因不支持此功能吗?

想象一下,我为 bash 编写了一个补丁/拉请求,是否存在\b无法实现的原因(除了“我们不喜欢这个功能”等原因)?

答案1

根据bash手册页,该=~运算符似乎正在使用 POSIX 正则表达式函数:

当您使用 时=~,运算符右侧的字符串被视为 POSIX 扩展正则表达式模式并进行相应匹配(使用通常在 中描述的POSIXregcomp和接口)。regexecregex(3)

\b序列是Perl 正则表达式语法并且不是 POSIX 的一部分,因此 Bash 使用的库似乎不支持它。因此,在 Bash 中支持它可能意味着更改库,这通常会产生重大副作用。

这样做不太可能纯粹是为了适应这个语法元素。

答案2

首先检查 Bash 是否有自己的 RE 实现,或者它是否只使用系统库中的一个。

但是,是的,\b来自 Perl 正则表达式,一般来说,它们还包含大量标准正则表达式中不可用的其他扩展。尽管 GNU 系统似乎支持\s空格和\w单词字符,但不\d支持数字。我不知道为什么他们决定选择那些奇怪的,但总的来说,全部Perl RE 功能可能会使 RE 引擎变得更加复杂,尽管 Perl 粉丝可能喜欢它,但许多标准工具的作者可能不希望这样。然后,如果你开始添加这个那个,但不是全部,那么决定在哪里划清界限就成了一个问题。

无论如何,单词边框一开始就是不标准的。在一些系统上,\<\>应该适用于左右边框,而在 FreeBSD 和 Mac 上,您需要[[:<:]][[:>:]]

碰巧,就像 @steeldriver 评论一样,\b似乎也适用于 GNU,至少在我测试时是这样。只是在 Bash 中,您需要首先将 RE 存储在变量中,以避免特殊字符被 shell 的解析过程混淆:

$ re='\bWORD\b'; if [[ WORD =~ $re ]]; then echo y; else echo n; fi
y
$ re='\<WORD\>'; if [[ WORD =~ $re ]]; then echo y; else echo n; fi
y
$ re='\bWORD\b'; if [[ WORDLESS =~ $re ]]; then echo y; else echo n; fi
n
$ re='\<WORD\>'; if [[ WORDLESS =~ $re ]]; then echo y; else echo n; fi
n

相关内容