2011-11-24 72 views
2

下面提到的RegEx在非常大的字符串或超過2000行中執行得非常糟糕。基本上Java String由PL/SQL腳本組成。優化Java代碼中的多個RegEx

1-將每個出現的定界字符,例如||,!=或>符號替換爲字符前後的空格。這需要無限的時間,永不結束,所以不能記錄時間。

// Delimiting characters for SQLPlus 
private static final String[] delimiters = { "\\|\\|", "=>", ":=", "!=", "<>", "<", ">", "\\(", "\\)", "!", ",", "\\+", "-", "=", "\\*", "\\|" }; 


for (int i = 0; i < delimiters.length; i++) { 
    script = script.replaceAll(delimiters[i], " " + delimiters[i] + " "); 
} 

2-以下模式查找所有正斜槓的發生/除了前面帶*的那些。這意味着不要在塊註釋語法中查找正斜槓。對於2000行的字符串,這需要大約103秒。

Pattern p = Pattern.compile("([^\\*])([\\/])([^\\*])"); 
Matcher m = p.matcher(script); 
while (m.find()) { 
    script = script.replaceAll(m.group(2), " " + m.group(2) + " "); 
} 

3-從日期或日期格式

Pattern p = Pattern.compile("(?i)(\\w{1,2}) +/ +(\\w{1,2}) +/ +(\\w{2,4})"); 
// Create a matcher with an input string 
Matcher m = p.matcher(script); 
while (m.find()) { 
    part1 = script.substring(0, m.start()); 
    part2 = script.substring(m.end()); 
    script = part1 + m.group().replaceAll("[ \t]+", "") + part2; 
    m = p.matcher(script); 
} 

內刪除所有空格有沒有什麼辦法讓他們花費更少的時間來優化所有的三個正則表達式?

感謝

阿里

+2

你應該把這個問題分成三個單獨的問題。這也將幫助您創建比「優化多個正則表達式」更有意義(因此也更有趣)的問題標題...... –

回答

2

我來回答第一個問題。

可這一切都合併到一個單一的正則表達式替換操作:

script = script.replaceAll("\\|\\||=>|[:!]=|<>|[<>()!,+=*|-]", " $0 "); 

說明:

\|\|   # Match || 
|    # or 
=>    # => 
|    # or 
[:!]=   # := or != 
|    # or 
<>    # <> 
|    # or 
[<>()!,+=*|-] # <, >, (,), !, comma, +, =, *, | or - 
+0

但這樣會更快嗎?我對此表示懷疑。 – FailedDev

+0

@FailedDev:我很確定它會。最初的解決方案將採用'a:= b || c',將其轉換爲'a:= b || c',然後將其轉換爲'a:= b || c',然後進入'a:= b || c',然後進入'a:= b | | (我只展示了實際發生的事情的步驟,而且我肯定這不是他打算髮生的事情)。由此引入的大量雙空間不會在這裏出現,但您可以獲得大致的想法。 –

+0

是的你有一個好點。 +1 – FailedDev

1

肯定。你的第二種方法是「幾乎」好。問題是你不使用你的模式來替換它自己。當您使用str.replaceAll()時,實際上每次調用此方法時都會創建Pattern實例。 Pattern.compile()被稱爲你,它需要90%的時間。

您應該使用Matcher.replaceAll()來代替。

String script = "dfgafjd;fjfd;jfd;djf;jds\\fdfdf****\\/"; 
    String result = script; 

    Pattern p = Pattern.compile("[\\*\\/\\\\]"); // write all characters you want to remove here. 
    Matcher m = p.matcher(script); 
    if (m.find()) { 
     result = m.replaceAll(""); 
    }  
    System.out.println(result); 
1

這不是你造成性能問題的正則表達式,它是事實,你正在做許多越過文本,不斷創造新的模式對象。正如Tim所指出的那樣,這不僅僅是表現如此糟糕,當你這樣做的時候,先前的通行證的結果太容易了。

事實上,我猜測日期中的那些額外空間只是副作用,您的其他替代品。如果是的話,這裏有一個方法,你可以做所有的替換在一次通過,而不會增加不必要的字符:

static String doReplace(String input) 
{ 
    String regex = 
     "/\\*[^*]*(?:\\*(?!/)[^*]*)*\\*/|"  // a comment 
    + "\\b\\d{2}/\\d{2}/\\d{2,4}\\b|"   // a date 
    + "(/|\\|\\||=>|[:!]=|<>|[<>()!,+=*|-])"; // an operator 

    Matcher m = Pattern.compile(regex).matcher(input); 
    StringBuffer sb = new StringBuffer(); 
    while (m.find()) 
    { 
    // if we found an operator, replace it 
    if (m.start(1) != -1) 
    { 
     m.appendReplacement(sb, " $1 "); 
    } 
    } 
    m.appendTail(sb); 
    return sb.toString(); 
} 

see the online demo

的訣竅是,如果你不叫appendReplacement(),本場比賽位置沒有更新,所以就好像沒有發生匹配。因爲我忽略了它們,所以將註釋和日期與其他不匹配的文本一起重新插入,我不必擔心匹配內部的斜槓字符。

編輯確保正則表達式的「註釋」部分位於「運算符」部分之前。否則,每個評論的前導/將被視爲運營商。