使用RegEx解析大字符串时出现java.lang.StackOverflowError

这是我的正则表达式


((?:(?:'[^']*')|[^;])*)[;]

它在分号上标记字符串。例如,


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)

这是怎么引起的,我该如何解决?


慕容708150
浏览 1012回答 3
3回答

幕布斯6054654

不幸的是,Java的内置正则表达式支持对包含重复性替代路径(即(A|B)*)的正则表达式存在问题。这被编译为递归调用,当在非常大的字符串上使用时,将导致StackOverflow错误。一种可能的解决方案是重写正则表达式以不使用重复性替代方法,但是如果您的目标是在分号上标记字符串,那么您实际上根本不需要复杂的正则表达式,只需使用String.split()和简单";"的论据。

郎朗坤

如果确实需要使用使堆栈溢出的正则表达式,则可以通过将-Xss40m之类的内容传递给JVM来增加堆栈的大小。

慕虎7371278

在+之后添加a可能会有所帮助[^;],从而减少重复次数。难道没有某种结构会说“如果正则表达式匹配到这一点,请不要回溯”?也许也派上用场。(更新:它被称为所有格修饰符)。完全不同的选择是编写一个称为的实用程序方法splitQuoted(char quote, char separator, CharSequence s),该方法显式遍历字符串并记住它是否已看到奇数个引号。在该方法中,您还可以处理引号字符出现在带引号的字符串中时可能需要不转义的情况。'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.
打开App,查看更多内容
随时随地看视频慕课网APP