回溯中的量词范围未起作用

5

好的,我正在处理一个项目,需要用到一个正则表达式来匹配一个*后面跟着1-4个空格或制表符,然后再跟一行文本。目前为止,我在测试目的下使用.* 来匹配lookbehind之后的内容。但是我只能显式地匹配1、2或4个空格/制表符,而不能匹配1-4个。我正在针对以下块进行测试

*    test line here
*   Second test
*  Third test
* Another test

以下是我正在测试的两种模式(?<=(\*[ \t]{3})).*,它按预期工作并匹配第二行,如果我用1、2或4替换3,结果相同。然而,如果我将其替换为1,4形成以下模式(?<=(\*[ \t]{1,4})).*,它就不再匹配任何行了,我实在不明白为什么。我已经试过搜索但没有成功。我正在使用全局标志 g。

1个回答

5

PHP和其他许多语言一样,不支持变长回顾后发。唯一的支持是在回顾后发的顶层使用交替 (|)。即使一个?也可能破坏模式匹配。另一种选择是使用:

(?<=\*[ \t]|\*[ \t]{2}|\*[ \t]{3}|\*[ \t]{4}).*

或者更好的方法是,终止对组的回顾:
\*[ \t]{1,4}(.*)

这对您来说应该很有效,因为似乎您的匹配没有重叠。
根据手册:
回顾断言的内容受到限制,以使其匹配的所有字符串都必须具有固定长度。但是,如果有几个替代方案,则它们不必都具有相同的固定长度。因此,(?<=bullock|donkey)是允许的,但是(?
来源:http://www.php.net/manual/en/regexp.reference.assertions.php

1
值得一提的是,正则表达式仍然不能实现 OP 可能想要的功能 - 它会匹配超过 4 个空格,因为 .* 会很好地匹配空格。 - Tim Pietzcker
1
@Tim - 这是一个很好的观点,但我认为.*只是OP认为奇怪行为的简化示例 - 有趣的部分是向后查找。 - Kobi
谢谢,我忽略了那个。顺便说一下,RegexBuddy对于{1,4}并没有抱怨(它对无限量词有些犹豫,但对于这个有限量词却没有)。 - Tim Pietzcker
经过一些交替测试,似乎它总是只匹配后面跟着一个空格的*,因此导致匹配区域以制表符或空格开头,但我想我可以像你说的那样中止回顾组,然后通过字符串操作删除不必要的空格。我想我可以使用子字符串来删除第一个字符,然后使用ltrim。是的,.*只是简化了代码,因为我需要帮助的是回顾组。 - Hultner
@Tim - 我想这取决于实现方式:{1,4}可以扩展为合法的替代,但PHP不这样做(当然更好,否则可能会创建一个畸形)。我在http://www.pagecolumn.com/tool/pregtest.htm上检查我的PHP模式,有时也在ideone上检查,我猜它们更接近真实情况 :) - Kobi
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接