[英]Java regex to match start/end tags causes stack overflow
Java
Pattern
類的標准實現使用遞歸來實現多種形式的正則表達式(例如,某些運算符、交替)。
這種方法會導致超過(相對較小)長度的輸入字符串出現堆棧溢出問題,長度甚至可能不超過 1,000 個字符,具體取決於所涉及的正則表達式。
一個典型的例子是以下正則表達式使用交替從周圍的 XML 字符串中提取可能的多行元素(名為Data
),該字符串已經提供:
<Data>(?<data>(?:.|\r|\n)+?)</Data>
上述正則表達式與Matcher.find()
方法一起使用以讀取“數據”捕獲組並按預期工作,直到提供的輸入字符串的長度超過 1,200 個字符左右,在這種情況下會導致堆棧溢出。
可以重寫上面的正則表達式以避免堆棧溢出問題嗎?
有關堆棧溢出問題起源的更多詳細信息:
有時正則表達式
Pattern
類會拋出StackOverflowError
。 這是已知錯誤 #5050507的表現,自 Java 1.4 以來,該錯誤一直存在於java.util.regex
包中。 該錯誤將繼續存在,因為它處於“無法修復”狀態。 出現此錯誤是因為Pattern
類將正則表達式編譯成一個小程序,然后執行該程序以查找匹配項。 這個程序是遞歸使用的,有時當遞歸調用太多時會出現這個錯誤。 有關更多詳細信息,請參閱錯誤描述。 似乎它主要是由使用交替觸發的。
您的正則表達式(有交替)匹配兩個標簽之間的任何 1+ 個字符。
您可以使用帶有Pattern.DOTALL
修飾符(或等效的嵌入標志(?s)
)的惰性點匹配模式,這將使.
也匹配換行符:
(?s)<Data>(?<data>.+?)</Data>
然而,在大量輸入的情況下,惰性點匹配模式仍然會消耗大量內存。 最好的方法是使用unroll-the-loop 方法:
<Data>(?<data>[^<]*(?:<(?!/?Data>)[^<]*)*)</Data>
查看正則表達式演示
詳情:
<Data>
- 文字文本<Data>
(?<data>
- 捕獲組“數據”的開始
[^<]*
- 除<
之外的零個或多個字符(?:<(?!/?Data>)[^<]*)*
- 0 個或多個序列:
<(?!/?Data>)
- 一個<
后面沒有跟Data>
或/Data>
[^<]*
- 除<
之外的零個或多個字符)
- “數據”組的結尾</Data>
- 結束分隔符
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.