前几天,我开始考虑如何实现正则表达式引擎,我提出的一个潜在问题涉及零宽度前瞻和重复。例如,当匹配字符串/((?=x))*/
上的正则表达式(额外括号以避免无效语法)"xx"
时,将尝试尽可能多地匹配内部组。因为,从字符串的开头开始,ZWLA通过,它被认为是匹配,但不消耗任何字符。因此,有人可能会认为正则表达式引擎可能会进入无限循环。
在GNU C ++ 11中测试时,regex_match
返回false
。
在regex101上测试时,它会返回匹配。
这种正则表达式构造会被视为“不良形式”吗?或者这种事情是否存在标准行为?
答案 0 :(得分:1)
这种正则表达式构造会被视为“不良形式”吗?或者这种事情是否存在标准行为?
不,((?=x))
是有效的正则表达式。它匹配x
之前的空字符串。
为什么要匹配空字符串?
在某些情况下,需要匹配空字符串。通常的应用之一是使用某种Regex.Split
拆分 。
有人可能会认为正则表达式引擎可能会进入无限循环。
这确实是一个值得考虑的问题。大多数正则表达式引擎实现都具有自己的多重匹配机制。他们中的大多数在每次检查后将正则表达式索引移动到下一个可用位置。在JS中,您需要将g
与match()
一起使用,exec()
(同样,test()
也会这样做)并且引擎将推进lastIndex
属性。所有主要语言都将采用类似的方式(C#Regex.Matches
,Java while (matcher.find())
,Pythons re.finditer/re.findall
等)。但是,有时候,必须手动移动索引(这是JS中works和this one将导致无限循环的示例。
至于为什么你在C ++中没有匹配,很容易解释:regex_match
期望整个字符串匹配。如果您使用regex_search
,您将获得与空字符串的成功匹配,因为/((?=x))*/
正则表达式将匹配第一个x
之前的空字符串(如果您不启用多个搜索)。
string data("xx");
std::regex pattern("((?=x))*");
std::smatch result;
if (regex_search(data, result, pattern)) {
std::cout << "\"" << result[0].str() << "\"" << std::endl;
}
else
{
std::cout << "regex_search failed!" << std::endl;
}
if (regex_match(data, result, pattern)) {
std::cout << result[0].str() << std::endl;
}
else
{
std::cout << "regex_match failed!" << std::endl;
}
结果:
""
regex_match failed!