2013-02-14 99 views
9

我試圖清理所有非文字字符的字符串,除非它是&即模式可能會像&[\w]+;刪除所有非單詞字符,除非&或'模式

例如:

abc; => abc 
abc & => abc & 
abc& => abc 

如果我使用string.replaceAll("\W","")它刪除;'&'也從我不想要的第二個例子。

可以在這個問題中使用負面預測可以給出一個快速解決方案正則表達式模式?

+1

+1非常好的問題。 – 2013-02-14 18:37:35

回答

2

首先,我真的很喜歡這個問題。現在,你想要什麼不能用一個replaceAll來完成,因爲爲此,我們需要一個長度可變的negative look-behind,這是不允許的。如果允許的話,那就不會那麼困難了。

無論如何,因爲單個replaceAll在這裏沒有選擇,你可以在這裏使用一些小技巧。就像第一個替換你的最後一個semi-colonentity reference,用一些字符序列,你肯定不會在字符串的其餘部分存在,如XXX或任何東西。我知道這是不正確的,但你肯定無法幫助它。

所以,這裏是你可以嘗試什麼:

String str = "a;b&c &"; 

str = str.replaceAll("(&\\w+);", "$1XXX") 
      .replaceAll("&(?!\\w+?XXX)|[^\\w&]", "") 
      .replaceAll("(&\\w+)XXX", "$1;"); 

System.out.println(str); 

說明:

  • 第一的replaceAll,取代像&模式與&ampXXX,或更換爲去年;任何其他序列。
  • 第二個替換全部,替換任何&後面跟着\\w+XXX或任何non-word, non &字符。這將取代所有不屬於&類型模式的所有&'s。另外,還可以替換任何其他非單詞字符。
  • 第三的replaceAll,重新替換XXX;,創建回&&ampXXX

,並使其更容易理解,你可以比較使用PatternMatcher類和我總是喜歡在更換標準複雜時使用它們。

String str = "a;b&c &"; 

Pattern pattern = Pattern.compile("&\\w+;|[^\\w]"); 
Matcher matcher = pattern.matcher(str); 

StringBuilder sb = new StringBuilder(); 

while (matcher.find()) { 
    String match = matcher.group(); 
    if (!match.matches("&\\w+;")) { 
     matcher.appendReplacement(sb, ""); 
    } else { 
     matcher.appendReplacement(sb, match); 
    } 
} 
matcher.appendTail(sb); 
System.out.println(sb.toString()); 

這個和Eric的代碼很相似,但是它是一個泛化。那個只會在&的情況下工作,當然如果它被改進去除NullPointerException就會被拋出。

+0

好的答案,儘管一開始我想要一個更緊湊的解決方案。 – dreamcrash 2013-02-14 19:25:36

+0

@dreamcrash。如果Java Regex允許可變長度後視,它本來可能很小巧。在這種情況下,替換將如下所示:'str.replaceAll(「(?<!&\\w+); |&(?!\\ w + - )| [^ \\ w;&]」,「」);' – 2013-02-14 19:39:39

+0

@dreamcrash。AFAIK,一些正則表達式引擎確實允許可變長度的後視圖,但是我不記得它們是哪個。 – 2013-02-14 19:40:16

0

我會建議你使用負前瞻是這樣的:

string.replace(/&(?!\w+;)/ig, ''); 

它取代所有&後面沒有分號結尾的單詞字符。

EDIT(JAVA):

string.replaceAll("/&(?!\w+;)/i", ''); 
+0

哈哈,我讀過「javascript」...所以我的編輯接近於Java應該工作。 – migg 2013-02-14 18:27:52

2

我不知道,你可以使用一個簡單的String.replaceAll做到這一點。您應該使用PatternMatcher來循環匹配,有效地進行手動搜索和替換。像下面的代碼應該做的伎倆。

public String replaceString(String origString) { 
    Pattern pattern = Pattern.compile("&(\w+);|[^\w]"); 
    Matcher matcher = pattern.matcher(origString); 
    StringBuffer sb = new StringBuffer(); 
    while (matcher.find()) { 
     if (matcher.group().startsWith("&") && !matcher.group(1).equals("amp")) { 
      matcher.appendReplacement(sb, matcher.group()); 
     } else { 
      matcher.appendReplacement(sb, ""); 
     } 
    } 
    matcher.appendTail(sb); 
    return sb.toString(); 
} 
+0

+1感謝您的解決方案! – Watt 2013-02-15 19:04:12

相關問題