【发布时间】:2014-01-16 08:39:40
【问题描述】:
一些背景知识:我正在实现一个正则表达式匹配引擎 (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 的回溯特定行为的建议很可能是错误的......
【问题讨论】:
-
我曾经犯过一个错误,就是看看它是如何完成的。 SCARY! 据我所知,完整的 PCRE 需要堆栈评估模型,而不是自动机理论模型。与基于自动机的方法最接近的可能是 PostgreSQL 和 Tcl 中使用的 RE 引擎,但这真的很复杂。
-
感谢您的快速回复。但这似乎不是回溯的特定行为(请参阅编辑),并且可以使用自动机实现(尽管我知道 TRE 未能通过 AT&T 测试数据存储库的一些 POSIX 合规性测试,因此,这种行为可能是一种“错误")。