9

我正在尝试清除所有非单词字符的字符串,除非它是 & 即模式可能就像&[\w]+;

例如:

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

如果我使用它,它也会从我不想要的第二个示例中string.replaceAll("\W","") 删除。;'&'

在这个问题中使用负前瞻可以快速解决正则表达式模式吗?

4

3 回答 3

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();
}
于 2013-02-14T18:38:54.943 回答
2

首先,我真的很喜欢这个问题。现在,你想要的不能用一个来完成replaceAll,因为为此,我们需要一个negative look-behind可变长度的,这是不允许的。如果允许的话,就不会那么难了。

无论如何,由于replaceAll这里没有选择单身,你可以在这里使用一点技巧。就像首先用一些字符序列替换semi-colon你中的最后一个,entity 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 替换模式,如&with &ampXXX,或替换为 last 的任何其他序列;
  • 第二个replaceAll,替换任何&后面没有的\\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扔在其中的东西时,它才会起作用。

于 2013-02-14T18:46:37.353 回答
0

我建议你使用这样的负前瞻:

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

它替换所有 & 后不跟以分号结尾的单词字符。

编辑(Java):

string.replaceAll("/&(?!\w+;)/i", '');
于 2013-02-14T18:24:54.800 回答