簡體   English   中英

嘗試在Java中使用正則表達式時出現堆棧溢出

[英]Stack overflow when trying to use regex in java

我已經閱讀了一些有關如何優化正則表達式的文章,但沒有一個答案(較少的組,使用{X,Y}而不是*)似乎阻止了我的正則表達式出現堆棧溢出錯誤。

我正在嘗試通過文件進行動態搜索。 可以說我在一個很大的文件(2-4 mb)中搜索“我敢打賭你找不到我”。 我的正則表達式生成器將生成正則表達式:

i(?:.|\s)*?bet(?:.|\s)*?you(?:.|\s)*?cannot(?:.|\s)*?find(?:.|\s)*?me

這個正則表達式的想法是,無論單詞之間有什么字符或空格,它都能找到確切的短語。 但是,當我嘗試使用時:

Pattern p = Pattern.compile(generatedRegex, Pattern.MULTILINE);
Matcher m = p.matcher(fileContentsAsString);
while (m.find()) {
System.out.println(m.group())
}

我收到堆棧溢出錯誤。 我知道正則表達式使用遞歸,但似乎這不是正則表達式的缺點。 有什么辦法可以優化此正則表達式? 謝謝!

回答:

Pattern p = Pattern.compile("i(?:.*)bet(?:.*)you(?:.*)cannot(?:.*)find(?:.*?)me", Pattern.DOTALL);

是我最終使用的模式/正則表達式。 似乎很快,不再出現堆棧溢出異常

我認為您由於不願意使用限定詞(*?)而獲得大量回溯。 防止回溯的一種方法是使用原子分組(?>X)和/或所有格限定符(*+)

根據評論,您還希望僅捕獲最接近“ bet”的“ i”,以減少總體比賽的時間。 由於您想獲得與其余單詞最接近的“ i”,因此在我為第二個單詞添加否定前瞻的地方,您也要為它的第一個單詞添加否定前瞻。 換句話說, (?!bet) (?!i)(?!bet)將變成(?!i)(?!bet)(?!i|bet) 我已編輯以下代碼以包含此要求。

String fileContentsAsString = "ii ... bet ... you, ibetyouyou";
String regex = "i(?>(?!i|bet).)*+bet(?>(?!you).)*+you";
Pattern p = Pattern.compile(regex, Pattern.DOTALL);
Matcher m = p.matcher(fileContentsAsString);
while (m.find()) {
    System.out.println(m.group());
}

輸出:

我..賭..你

ibetyou

說明 (來源)

“勉強的量詞的工作方式是,每次都要嘗試匹配時,它首先嘗試讓正則表達式的下一部分匹配。因此,它有效地在每次迭代的開始進行了前瞻,這可能會非常昂貴,尤其是當量化部分每次迭代僅匹配一個字符時,例如。*?”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM