标准执行情况Java
Pattern
类使用递归来实现多种形式的正则表达式(例如,某些运算符、交替)。
这种方法会导致输入字符串超过(相对较小)长度的堆栈溢出问题,该长度甚至可能不超过 1,000 个字符,具体取决于所涉及的正则表达式。
一个典型的示例是以下正则表达式,使用交替来提取可能的多行元素(名为Data
) 来自已提供的周围 XML 字符串:
<Data>(?<data>(?:.|\r|\n)+?)</Data>
上面的正则表达式与Matcher.find()
方法读取“数据”捕获组并按预期工作,直到提供的输入字符串的长度超过 1,200 个字符左右,在这种情况下会导致堆栈溢出。
可以重写上面的正则表达式来避免堆栈溢出问题吗?
有关的更多详细信息堆栈溢出问题的根源 http://www.javaworld.com/article/2077757/core-java/optimizing-regular-expressions-in-java.html?page=4:
有时正则表达式Pattern
类将抛出一个StackOverflowError
。这是一个体现已知错误#5050507 http://www.javaworld.com/article/2077757/core-java/optimizing-regular-expressions-in-java.html?page=4#resources,这已经在java.util.regex
从 Java 1.4 开始打包。该错误会一直存在,因为它处于“无法修复”状态。出现此错误的原因是Pattern
类将正则表达式编译成一个小程序,然后执行该程序以查找匹配项。该程序是递归使用的,有时当递归调用太多时会出现此错误。请参阅错误描述 http://www.javaworld.com/article/2077757/core-java/optimizing-regular-expressions-in-java.html?page=4#resources更多细节。看来它主要是通过使用交替来触发的。
您的正则表达式(具有交替)匹配两个标签之间的任何 1+ 个字符。
您可以使用惰性点匹配模式Pattern.DOTALL
修饰符(或等效的嵌入标志(?s)
)这将使.
也匹配换行符:
(?s)<Data>(?<data>.+?)</Data>
See 这个正则表达式演示 https://regex101.com/r/rY5mI2/1
然而,在输入巨大的情况下,惰性点匹配模式仍然会消耗大量内存。最好的方法是使用展开循环法 http://www.softec.lu/site/RegularExpressions/UnrollingTheLoop:
<Data>(?<data>[^<]*(?:<(?!/?Data>)[^<]*)*)</Data>
See the 正则表达式演示 https://regex101.com/r/oG5aE9/1
Details:
-
<Data>
- 文字<Data>
-
(?<data>
- start of the capturing group "data"
-
[^<]*
- 零个或多个字符以外的字符<
-
(?:<(?!/?Data>)[^<]*)*
- 0 or more sequences of:
-
<(?!/?Data>)
- a <
后面没有跟Data>
or /Data>
-
[^<]*
- 零个或多个字符以外的字符<
-
)
- “数据”组的末尾
-
</Data>
- 结束分隔符
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)