web-dev-qa-db-fra.com

Supprimer tous les caractères non "Word" d'une chaîne en Java, laissant des caractères accentués?

Apparemment, la saveur Regex de Java compte les trémas et autres caractères spéciaux comme des "non-caractères Word" lorsque j'utilise Regex.

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

renvoie "TESTTEST" pour moi. Ce que je veux, c'est que tous les caractères vraiment non "Word" soient supprimés. Toute façon de le faire sans avoir quelque chose comme

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

seulement pour réaliser que j'ai oublié ô?

66
Epaga

Utilisation [^\p{L}\p{Nd}]+ - cela correspond à tous les caractères (Unicode) qui ne sont ni des lettres ni des chiffres (décimaux).

En Java:

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

Modifier:

J'ai changé \p{N} à \p{Nd} car le premier correspond également à certains symboles numériques comme ¼; ce dernier non. Voir sur regex101.com .

154
Tim Pietzcker

J'essayais d'obtenir exactement le contraire lorsque je suis tombé sur ce fil. Je sais que c'est assez ancien, mais voici ma solution quand même. Vous pouvez utiliser des blocs, voir ici . Dans ce cas, compilez le code suivant (avec les bonnes importations):

> 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(), "#"));

Vous devriez voir la sortie suivante:

vrai

#blabla

Meilleur,

7
Mena

Parfois, vous ne voulez pas simplement supprimer les caractères, mais simplement supprimer les accents. J'ai créé la classe d'utilitaires suivante que j'utilise dans mes projets Web Java REST chaque fois que j'ai besoin d'inclure une chaîne dans une 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;
    }
}

En tant que locuteur allemand, j'ai également inclus la gestion appropriée des trémas allemands - la liste devrait être facile à étendre pour d'autres langues.

HTH

EDIT: Notez qu'il peut être dangereux d'inclure la chaîne retournée dans une URL. Vous devez au moins le coder en HTML pour empêcher les attaques XSS.

6
Stefan Haberl

Eh bien, voici une solution avec laquelle je me suis retrouvé, mais j'espère qu'il y en a une plus élégante ...

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 aboutit au résultat souhaité ...

2
Epaga

Vous voudrez peut-être supprimez d'abord les accents et les signes diacritiques , puis à chaque position de caractère, vérifiez si la chaîne "simplifiée" est une lettre ascii - si c'est le cas, la position d'origine doit contenir des caractères Word, sinon , il peut être supprimé.

1
István