使用正则表达式解析大字符串时出现java.lang.StackOverflowerError

使用正则表达式解析大字符串时出现java.lang.StackOverflowerError,java,regex,stack-overflow,Java,Regex,Stack Overflow,这是我的正则表达式 ((?:(?:'[^']*')|[^;])*)[;] 它用分号表示字符串。比如说, Hello world; I am having a problem; using regex; 结果是三个字符串 Hello world I am having a problem using regex 但是当我使用一个大的输入字符串时,我得到了这个错误 Exception in thread "main" java.lang.StackOverflowError at java.u

这是我的正则表达式

((?:(?:'[^']*')|[^;])*)[;]
它用分号表示字符串。比如说,

Hello world; I am having a problem; using regex;
结果是三个字符串

Hello world
I am having a problem
using regex
但是当我使用一个大的输入字符串时,我得到了这个错误

Exception in thread "main" java.lang.StackOverflowError
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
at java.util.regex.Pattern$Loop.match(Pattern.java:4295)
at java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
at java.util.regex.Pattern$BranchConn.match(Pattern.java:4078)
at java.util.regex.Pattern$CharProperty.match(Pattern.java:3345)
at java.util.regex.Pattern$Branch.match(Pattern.java:4114)
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
at java.util.regex.Pattern$Loop.match(Pattern.java:4295)
at java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)

这是如何导致的,我如何解决它?

不幸的是,Java的内置正则表达式支持在包含重复替代路径的正则表达式中存在问题(即,
(A | B)*
)。这被编译成递归调用,当在非常大的字符串上使用时,会导致StackOverflow错误


一个可能的解决方案是重写您的正则表达式,使其不使用repitive替代项,但是如果您的目标是在分号上标记字符串,那么您实际上根本不需要复杂的正则表达式,只需使用一个简单的
“;”
作为参数。

[^;]
之后添加一个
+
,可能会有所帮助,这样你的重复次数就少了

是否也有一些结构说“如果正则表达式匹配到这一点,不要回溯”?也许这也能派上用场。(更新:它被称为)

另一种完全不同的方法是编写一个名为
splitquote(char quote,char separator,CharSequence)
的实用程序方法,该方法显式迭代字符串并记住它是否看到奇数个引号。在该方法中,还可以处理引号字符出现在引号字符串中时可能需要取消其范围的情况

'I'm what I am', said the fox; and he disappeared.
'I\'m what I am', said the fox; and he disappeared.
'I''m what I am', said the fox; and he disappeared.

如果您真的需要使用溢出堆栈的正则表达式,您可以通过向JVM传递类似-Xss40m的内容来增加堆栈的大小。

大多数正则表达式引擎都会遇到这个问题。我想我没有清楚地说明我的情况,对此表示抱歉。字符串不只是在分号上标记,而是同时在许多模式上标记,在分号上标记只是一个简单的例子。@Ali好的,一般来说:尽量避免在通配符中使用替代符。您还可以尝试使用jregex等其他正则表达式库,尽管我不确定这是否能解决问题…@NullUserException至少不是JavaScript。我在1600个字符以上的字符串上做同样的操作。它给了我Java中的StackOverflower错误。但是JavaScript在1毫秒内给了我正确的结果。我真的很震惊,在这个简单的任务中,一种编译语言,加上它所有可能的优化,在性能方面可能比一种解释语言表现得更差。您可以自己尝试(F12中的浏览器控制台):
function test(str){console.time(“test”);console.log(/^([^']|'[^']*]*$/.test(str));console.timeEnd(“test”)}
然后
测试(“1000+字符字符串”)
您正在解析的字符串有多大?这个问题很老,但是,我可以使用所有格限定符(
*+
而不是
*
)来解决类似的问题,以避免回溯,因此我应该使用原子组
(?>)
而不是组
(?:…)
,始终防止回溯通过Xss属性增加堆栈大小将增加OutOfMemoryError的可能性。尽管它将解决当前的问题。帮助我解决了在启动eclipse时看到的堆栈溢出错误。我看到的错误是无法为org.robotframework.red.robotsuitefile_robot创建内容描述符。内容类型已被禁用。栈溢出