PHP使用PCRE正则表达式库,它不支持在lookbehinds中重复。
如果重复是在后面(例如,(?<=\d+)
),PHP通常会发出如下警告:
警告:preg_match_all():编译失败:在第10行的lookbehind.php中,lookbehind断言在偏移量7处不是固定长度
但是,我发现在我认为应该编译时不会失败的情况。
这些无法按预期编译:
/(?<=X*)a/
/(?<=X+)a/
/(?<=(X)*)a/
但是,/(?<=(X)+)a/
会编译。这应该在功能上等同于/(?<=(X){1,})a/
,它也可以编译。另一方面,如果我实际上添加了该范围的上限
(例如,/(?<=(X){1,2})a/
),无法编译。我认为/(?<=(X)+)a/
和/(?<=(X){1,})a/
也应该无法编译,但他们没有。为什么不呢?
以下是一些代码:
$str = 'aXaaXXaaaXXXaaaa';
$regex = '/(?<=((?:X)+))a+/';
preg_match_all($regex, $str, $matches, PREG_OFFSET_CAPTURE|PREG_SET_ORDER);
print_r($matches);
我稍微复杂了模式,在多个X
周围添加了一个捕获组。以下是我的结果:
Array (
[0] => Array (
[0] => Array (
[0] => aa
[1] => 2
)
[1] => Array (
[0] => X
[1] => 1
)
)
[1] => Array (
[0] => Array (
[0] => aaa
[1] => 6
)
[1] => Array (
[0] => X
[1] => 5
)
)
[2] => Array (
[0] => Array (
[0] => aaaa
[1] => 12
)
[1] => Array (
[0] => X
[1] => 11
)
)
)
它显然与a
后面的X
匹配,这是正确的。但是,子模式1似乎只匹配一个X
,而不是所有a
。如果我在lookbehind的开头添加X
,以便它必须找到介于两者之间的所有$regex = '/(?<=(a(?:X)+))a+/';
,这是我的结果:
Array (
[0] => Array (
[0] => Array (
[0] => aa
[1] => 2
)
[1] => Array (
[0] => aX
[1] => 0
)
)
)
X
它只匹配一次(只有一个(X)+
)。实际上,(X){1,}
和(X){1}
正在减少到+
(由于其固定长度,这是允许的)。
我不想哭,“虫子!”一旦我发现一些不符合我预期的东西,但它确实看起来像是一个。模式不会像我期望的那样被拒绝,然后即使它是一个有效的模式,它也不像我期望的那样。
所以我问:
*
但不适用于X+
?(X)+
失败;允许{{1}}?非常感谢任何见解。谢谢。
答案 0 :(得分:1)
这不是PHP错误。如果它是一个错误(它看起来像一个),它是一个PCRE错误,应该在那里报告。但是,请检查phpinfo()
中的PCRE版本并将其与最新版本进行比较。如果它不是最新的,请在发布错误报告之前直接在最新的PCRE中运行相同的正则表达式。
答案 1 :(得分:1)
PCRE版本8.32-RC1 2012-08-08
重新&GT; /(&LT; =(X)+)A / 失败:lookbehind断言在偏移量8处不是固定长度 重新&GT;
可能是一个错误。请更新到最新的PCRE。
顺便说一句,您可以使用\ K来创建无限制的反向引用。