据我所知,\b
bash 不支持指示“单词边界”的元序列:
if [[ $foo =~ .*\bWORD\b.* ]]; then
有什么原因不支持此功能吗?
想象一下,我为 bash 编写了一个补丁/拉请求,是否存在\b
无法实现的原因(除了“我们不喜欢这个功能”等原因)?
答案1
根据bash
手册页,该=~
运算符似乎正在使用 POSIX 正则表达式函数:
当您使用 时
=~
,运算符右侧的字符串被视为 POSIX 扩展正则表达式模式并进行相应匹配(使用通常在 中描述的POSIXregcomp
和接口)。regexec
regex(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