PHP 5.6正则表达式匹配异常及preg_match未返回FALSE问题咨询
preg_match('#\b(39||90)\b#')会出现异常匹配行为? 你遇到的这个问题本质是PHP使用的PCRE正则引擎对空分支的解析规则,以及单词边界\b的零宽特性共同导致的,下面一步步拆解原因:
1. PCRE对||的解析逻辑
你写的(39||90)在PCRE中并不是语法错误——它会被解析为三个备选分支:39、空字符串、90,等价于显式写法(39|90|)。这就是为什么preg_match没有返回false的原因:PCRE允许空分支存在,所以正则本身是合法的。
而regex101标记这个模式无效,是因为它默认使用的引擎(比如JavaScript)或者语法检查规则不允许连续的|(认为这是语法错误),但PCRE对这种写法是兼容的。
2. 为什么'42'会匹配成功?
你的正则完整逻辑是:匹配单词边界 + (39/空字符串/90) + 单词边界。当匹配空字符串分支时,正则简化为\b\b——两个连续的单词边界断言。
单词边界\b是零宽断言,它匹配的是“一侧是单词字符(\w,即字母、数字、下划线),另一侧是非单词字符或字符串首尾”的位置。对于'42'来说:
- 字符串开头(
^与4之间)是一个单词边界; - 字符串结尾(
2与$之间)也是一个单词边界。
由于空字符串不占用任何字符,\b\b实际上是在同一个单词边界位置上连续做两次断言——而PCRE允许这种连续的零宽断言匹配,所以'42'的开头或结尾位置会被成功匹配,导致preg_match返回1。
3. 为什么空字符串''匹配失败?
空字符串中不存在任何符合\b定义的位置:\b要求至少一侧有单词字符,但空字符串没有任何字符,自然找不到满足条件的单词边界。因此\b\b无法匹配空字符串,preg_match返回0。
解决建议
如果你的需求是匹配39、空字符串、90这三种情况,建议写成显式的空分支(39|90|),这样更清晰,也能避免不同引擎的解析差异;如果你的实际需求只是匹配39或90,直接去掉多余的|,写成(39|90)即可。
内容的提问来源于stack exchange,提问作者marekful

