惰性量词在PCRE中的工作原理如何?
一点背景:我正在实现一个正则表达式匹配引擎(NFA),它应该支持PCRE兼容模式(我的意思是它应该捕获与PCRE具有相同偏移量的子表达式)。
PCRE的testinput1中有一个我不能完全理解的测试。 它测试懒惰的量词。
所以,正则表达式是
/<a[s]+href[s]*=[s]* # find <a href=
(["'])? # find single or double quote
(?(1) (.*?)1 | ([^s]+)) # if quote found, match up to next matching
# quote, otherwise match up to next space
/isx
弦是
<a href="abcd xyz pqr" cats
PCRE的比赛是:
<a href="abcd xyz pqr"
显然是使用懒惰的量词。
据我所知,懒惰的量词不应该使用,直到另一个“贪婪”的方式是根本不可能的。 现在这里有一个可能的贪婪匹配:
<a href="abcd
它使用条件子模式的负分支,没有惰性量词。
所以我正在寻找这个PCRE行为的解释或任何细节/建议为什么懒惰量词在这个测试中匹配。 谢谢!
编辑 :我也检查了TRE库的工作原理。 它是POSIX兼容的NFA引擎。 我修改了原来的一些正则表达式以适应TRE的语法:
#include <stdlib.h>
#include <stdio.h>
#include <tre/tre.h>
int main()
{
regex_t preg;
const char * regex = "<a[ ]+href[ ]*=[ ]*(?:(')(.*?)'|[^ ]+)";
const char * string = "<a href='abcd xyz pqr' cats";
int cflags = REG_EXTENDED;
int eflags = 0;
size_t nmatch = 3;
regmatch_t pmatch[100];
tre_regcomp(&preg, regex, cflags);
tre_regexec(&preg, string, nmatch, pmatch, eflags);
for (int i = 0; i < nmatch; i++) {
printf("%d: (%d, %d)n", i, pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so);
}
return 0;
}
和输出(使用长度而不是结束偏移)是:
0: (0, 22)
1: (8, 1)
2: (9, 12)
所以关于PCRE的回溯特定行为的建议很可能是错误的......
首先,我只是REGEX世界的初学者。 所以,如果这个答案错了,或者我误解了这个问题,我很抱歉。
阅读本书定期表达食谱中的这个定义:
(?(1)then | else)是检查第一个捕获组是否已经匹配的条件。 如果有,则正则表达式引擎会尝试匹配。 如果截获组尚未参加比赛尝试,则尝试其他部分。
有了这个主题: <a href="abcd xyz pqr" cats
第一个捕获组匹配了第一个"
字符”,因此,预期的行为是尝试匹配当时的部分,然后第二个捕获组管理匹配字符串abcd xyz pqr
和(.*?)
,最后是然后部分设法匹配abcd xyz pqr"
与(.*?)1
。 REGEX可能会取得成功。
所以,其他的部分与它的量词不是必需的,事实上它不被使用。 这就好像该量词从未存在过。
有了这个主题: <a href="abcd
第一个捕捉组匹配了"
字符”,现在后面的部分设法将字符串abcd
与(.*?)
匹配,但它永远不会匹配最后一个"
字符,因为在主题末尾没有这样的字符。 条件失败。
REGEX引擎并没有停在这里,你已经使用过(["'])?
所以,引擎可能会再次尝试,因为"
角色是可选的,并且它继续进行,就好像第一个捕获组不匹配一样是回溯)。 因此,现在引擎达到了条件,不匹配第一个捕获组,其他部分尝试,并设法匹配字符串"abcd
( "
由于回溯, "
字符没有与第一个捕获组相匹配,现在它由其他部分中的第三个捕获组匹配)REGEX可能会成功完成。
PS:我正在学习有趣的东西,关于正则表达式,所以可能这个答案是完全错误的。 等待更好的答案。
我并不完全理解你的问题,但是非贪婪的量词允许搜索模式的第一次出现。 使用pcretest,您可以在相同的输入上尝试贪婪和非贪婪的表单。
非贪婪形式:
re> /<a[s]+href[s]*=[s]*(["'])?(?(1)(.*?)1|([^s]+))/i
data> <a href="ab"cd"
0: <a href="ab"
1: "
2: ab
贪婪的形式:
re> /<a[s]+href[s]*=[s]*(["'])?(?(1)(.*)1|([^s]+))/i
data> <a href="ab"cd"
0: <a href="ab"cd"
1: "
2: ab"cd
链接地址: http://www.djcxy.com/p/74797.html