繁体   English   中英

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

[英]java.lang.StackOverflowError while using a RegEx to Parse big strings

这是我的正则表达式

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

它用分号标记一个字符串。 例如,

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 错误。

一个可能的解决方案是重写您的正则表达式以不使用重复的替代方案,但是如果您的目标是在分号上标记字符串,那么您实际上根本不需要复杂的正则表达式,只需将String.split()与简单的";" 作为论据。

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

[^;]之后添加一个+可能会有所帮助,这样您就可以减少重复次数。

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

一个完全不同的替代方法是编写一个名为splitQuoted(char quote, char separator, CharSequence s)的实用方法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.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM