在Java中,如何从字符串中删除所有非“单词字符”,同时保留重音符号字符?

69

显然,当我使用Java的正则表达式时,其匹配规则将Umlauts和其他特殊字符视为非“单词字符”。

        "TESTÜTEST".replaceAll( "\\W", "" )

对我来说,返回的是"TESTTEST"。我想要的是只删除所有真正的非“单词字符”。有没有办法在不使用以下内容的情况下实现这一点


returns "TESTTEST" for me. What I want is for only all truly non-"word characters" to be removed. Any way to do this without having something along the lines of
         "[^A-Za-z0-9äöüÄÖÜßéèáàúùóò]"

只是意识到我忘记了ô?


整个Unicode参考[http://www.regular-expressions.info/unicode.html]。 - zaletniy
5个回答

163

使用[^\p{L}\p{Nd}]+ - 这将匹配所有既不是字母也不是(十进制)数字的(Unicode)字符。

在Java中:

String resultString = subjectString.replaceAll("[^\\p{L}\\p{Nd}]+", "");

编辑:

我将\p{N}更改为\p{Nd},因为前者还会匹配一些数字符号,例如¼;而后者不会。请在regex101.com上查看。


1
为什么在你的字符类中要使用 \\[ - Bart Kiers
2
非常好用!但无法替换 'º','ª','¼'。因为我只有一个 'º',所以我使用了 .replaceAll("[^\p{L}\p{N}]|º", ""); 请问如何去除其余的字符呢? - user952887

7

当我偶然看到这个帖子时,我正试图实现完全相反的目标。 我知道它已经很老了,但是这是我的解决方案。 您可以使用块,请参见此处。 在这种情况下,请编译以下代码(具有正确的导入):

> String s = "äêìóblah"; 
> Pattern p = Pattern.compile("[\\p{InLatin-1Supplement}]+"); // this regex uses a block
> Matcher m = p.matcher(s);
> System.out.println(m.find());
> System.out.println(s.replaceAll(p.pattern(), "#"));

你应该看到以下输出:

true

#blah

祝好,

6

有时候您并不是想要简单地删除字符,而只是想要删除重音符号。我设计了以下的实用类,我会在我的Java REST Web项目中使用它,每当我需要在URL中包含一个字符串时:

import java.text.Normalizer;
import java.text.Normalizer.Form;

import org.apache.commons.lang.StringUtils;

/**
 * Utility class for String manipulation.
 * 
 * @author Stefan Haberl
 */
public abstract class TextUtils {
    private static String[] searchList = { "Ä", "ä", "Ö", "ö", "Ü", "ü", "ß" };
    private static String[] replaceList = { "Ae", "ae", "Oe", "oe", "Ue", "ue",
            "sz" };

    /**
     * Normalizes a String by removing all accents to original 127 US-ASCII
     * characters. This method handles German umlauts and "sharp-s" correctly
     * 
     * @param s
     *            The String to normalize
     * @return The normalized String
     */
    public static String normalize(String s) {
        if (s == null)
            return null;

        String n = null;

        n = StringUtils.replaceEachRepeatedly(s, searchList, replaceList);
        n = Normalizer.normalize(n, Form.NFD).replaceAll("[^\\p{ASCII}]", "");

        return n;
    }

    /**
     * Returns a clean representation of a String which might be used safely
     * within an URL. Slugs are a more human friendly form of URL encoding a
     * String.
     * <p>
     * The method first normalizes a String, then converts it to lowercase and
     * removes ASCII characters, which might be problematic in URLs:
     * <ul>
     * <li>all whitespaces
     * <li>dots ('.')
     * <li>(semi-)colons (';' and ':')
     * <li>equals ('=')
     * <li>ampersands ('&')
     * <li>slashes ('/')
     * <li>angle brackets ('<' and '>')
     * </ul>
     * 
     * @param s
     *            The String to slugify
     * @return The slugified String
     * @see #normalize(String)
     */
    public static String slugify(String s) {

        if (s == null)
            return null;

        String n = normalize(s);
        n = StringUtils.lowerCase(n);
        n = n.replaceAll("[\\s.:;&=<>/]", "");

        return n;
    }
}

作为一个德语使用者,我已经包含了德语umlauts的正确处理 - 这个列表应该很容易扩展到其他语言。
希望有所帮助。
编辑:请注意,在URL中包含返回的字符串可能不安全。 为了防止XSS攻击,您至少应该对其进行HTML编码。

重要信息:您可以在http://commons.apache.org/lang/download_lang.cgi获取StringUtils类/包等。 - cV2
你从未使用过 slugify。 - Star
@Star slugify 是一个公共实用方法,可在您的代码中其他部分使用。 - Stefan Haberl

2

好了,这是我最终得出的一个解决方案,但我希望有更优雅的方式...

StringBuilder result = new StringBuilder();
for(int i=0; i<name.length(); i++) {
    char tmpChar = name.charAt( i );
    if (Character.isLetterOrDigit( tmpChar) || tmpChar == '_' ) {
        result.append( tmpChar );
    }
}
< p > result 最终得到了期望的结果...


1
你的变量String被命名为“name”,这表明它不会是一个很大的字符串。但在它确实变得很大(几千个字符)的情况下,我会像你现在所做的那样使用for语句。 - Bart Kiers

1

你可能需要首先删除重音符号和变音符号, 然后在每个字符位置检查“简化”字符串是否为ASCII字母 - 如果是,则原始位置应包含单词字符,否则可以删除。


Java.text.Normalizer类在Android API 9之前不受支持,因此如果您的应用程序必须与API级别8兼容(根据Google的Android仪表板,占总设备的13%),则此方法不可行。 - Giorgio Barchiesi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接