2013-02-14 85 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

相关问题