簡體   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