[英]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.