Удалить все не "словарные символы" из String в Java, оставив акцентированные символы?

По-видимому, ярлык Java Regex учитывает Umlauts и другие специальные символы как "словарные символы", когда я использую Regex.

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

возвращает "TESTTEST" для меня. То, что я хочу, это удаление только всех истинно не-словных символов. Любой способ сделать это, не имея что-то по строкам

         "[^A-Za-z0-9äöüÄÖÜßéèáàúùóò]"

только для того, чтобы понять, что я забыл?

Ответ 1

Используйте [^\p{L}\p{Nd}]+ - это соответствует всем (Unicode) символам, которые не являются ни буквами, ни (десятичными) цифрами.

В Java:

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

Edit:

Я изменил \p{N} на \p{Nd}, потому что первый также соответствует некоторым числовым символам, таким как ¼; последнее - нет. Посмотрите на regex101.com.

Ответ 2

Я пытался добиться совершенно противоположного, когда я столкнулся с этой нитью. Я знаю, что он довольно старый, но здесь мое решение тем не менее. Вы можете использовать блоки, см. здесь. В этом случае скомпилируйте следующий код (с правом импорта):

> 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

Бест,

Ответ 3

Иногда вы не хотите просто удалять символы, но просто удаляйте акценты. Я придумал следующий класс утилиты, который я использую в своих веб-проектах Java REST, когда мне нужно включить String в 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;
    }
}

Являясь немецким оратором, я включил правильную обработку немецких умляутов - список должен быть легко распространен для других языков.

НТН

EDIT: Обратите внимание, что может быть небезопасно включать возвращенную строку в URL-адрес. Вы должны по крайней мере HTML кодировать его, чтобы предотвратить атаки XSS.

Ответ 4

Ну, вот одно решение, с которым я закончил, но я надеюсь, что там будет более элегантный...

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 );
    }
}

result заканчивается желаемым результатом...

Ответ 5

Вы можете захотеть сначала удалить акценты и диакритические знаки, затем в каждой позиции персонажа проверьте, является ли "упрощенная" строка буквой ascii - если это так, исходная позиция должна содержать символы слова, если нет, ее можно удалить.

Ответ 6

Вы можете использовать StringUtils из apache