我正在尝试测试(使用boost::regex
)文件中的行是否仅包含由空格分隔的数字条目。我遇到了一个我不理解的异常(见下文)。如果有人可以解释为什么会抛出它,那就太好了。也许我在定义模式时在做一些愚蠢的事情?这是代码:
// regex_test.cpp
#include <string>
#include <iostream>
#include <boost/regex.hpp>
using namespace std;
using namespace boost;
int main(){
// My basic pattern to test for a single numeric expression
const string numeric_value_pattern = "(?:-|\\+)?[[:d:]]+\\.?[[:d:]]*";
// pattern for the full line
const string numeric_sequence_pattern = "([[:s:]]*"+numeric_value_pattern+"[[:s:]]*)+";
regex r(numeric_sequence_pattern);
string line= "1 2 3 4.444444444444";
bool match = regex_match(line, r);
cout<<match<<endl;
//...
}
我成功编译了
g++ -std=c++11 -L/usr/lib64/ -lboost_regex regex_test.cpp
到目前为止,最终的程序运行良好,而且match == true
依我所愿。但是后来我测试了一条输入线
string line= "1 2 3 4.44444444e-16";
当然,我的模式并不是为了识别格式4.44444444e-16
而建立的,我希望那是可以的match == false
。但是,相反,我得到以下运行时错误:
terminate called after throwing an instance of
'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::runtime_error> >'
what(): The complexity of matching the regular expression exceeded predefined bounds.
Try refactoring the regular expression to make each choice made by the state machine unambiguous.
This exception is thrown to prevent "eternal" matches that take an indefinite period time to locate.
这是为什么?
注意:我给出的示例是极端的,因为在点后面少放一位数字就可以了。那意味着
string line= "1 2 3 4.4444444e-16";
只是产生match == false
预期的结果。所以,我感到困惑。这是怎么回事
已经谢谢你了!
更新:
问题似乎已经解决。考虑到alejrb的提示,我将模式重构为
const string numeric_value_pattern = "(?:-|\\+)?[[:d:]]+(?:\\.[[:d:]]*)?";
这似乎应该工作。不知何故,\\.
原始模式内的孤立可选内容[[:d:]]+\\.?[[:d:]]*
留下了许多以不同方式匹配长数字序列的可能性。
我希望这种模式现在是安全的。但是,如果有人找到一种以新形式炸毁它的方法,请告诉我!对于我来说,这是否仍然可能还不是很明显。
我想说您的正则表达式可能成指数回溯。为了保护您免受循环的影响,如果输入不再存在,循环将变得完全不可行,正则表达式引擎会中止尝试。
经常导致此问题的一种模式是任何形式的(x+x+)+
-当您将第一种模式放置在第二种模式中时,会在此处建立该模式。
http://www.regular-expressions.info/catastrophic.html上有很好的讨论
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句