Entfernen Sie alle Nicht-Wort-Zeichen aus einem String in Java und lassen Sie Zeichen mit Akzent?

68

Anscheinend zählt Javas Regex-Geschmack Umlaute und andere Sonderzeichen als Nicht- "Wortzeichen", wenn ich Regex verwende.

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

gibt "TESTTEST" für mich zurück. Was ich möchte, ist, dass nur alle wirklich nicht "Wortzeichen" entfernt werden. Jeder Weg, dies zu tun, ohne etwas in der Art von zu haben

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

nur um zu erkennen, dass ich vergessen habe?

Epaga
quelle
Die gesamte Unicode-Referenz http://www.regular-expressions.info/unicode.html
zaletniy

Antworten:

159

Verwendung [^\p{L}\p{Nd}]+- Dies entspricht allen (Unicode-) Zeichen, die weder Buchstaben noch (Dezimal-) Ziffern sind.

In Java:

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

Bearbeiten:

Ich habe zu gewechselt \p{N}, \p{Nd}weil das erstere auch mit einigen Zahlensymbolen übereinstimmt, wie z ¼. Letzteres nicht. Sehen Sie es auf regex101.com .

Tim Pietzcker
quelle
1
Warum \\[in deiner Charakterklasse?
Bart Kiers
2
klappt wunderbar! ersetzt aber nicht 'º', 'ª', '¼'. da ich nur dieses 'º' habe, habe ich .replaceAll verwendet ("[^ \\ p {L} \\ p {N}] | º", ""); Irgendwelche Vorschläge, wie ich andere entfernen kann?
user952887
3
Upvoting sehr nützliche Antwort auf häufig auftretende \WProbleme.
zx81
@ TimPietzcker bitte können Sie mir mit diesem stackoverflow.com/questions/23797093/…
Axel
Wie kann ich das und Zahlen entfernen (nur Buchstaben lassen)?
Francisco Corrales Morales
7

Ich habe versucht, genau das Gegenteil zu erreichen, als ich auf diesen Thread gestoßen bin. Ich weiß, dass es ziemlich alt ist, aber hier ist trotzdem meine Lösung. Sie können Blöcke verwenden, siehe hier . Kompilieren Sie in diesem Fall den folgenden Code (mit den richtigen Importen):

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

Sie sollten die folgende Ausgabe sehen:

wahr

#blah

Beste,

Mena
quelle
6

Manchmal möchten Sie nicht einfach die Zeichen entfernen, sondern nur die Akzente. Ich habe die folgende Dienstprogrammklasse entwickelt, die ich in meinen Java REST-Webprojekten verwende, wenn ich einen String in eine URL einfügen muss:

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

Als Deutschsprachiger habe ich auch den richtigen Umgang mit deutschen Umlauten aufgenommen - die Liste sollte für andere Sprachen leicht zu erweitern sein.

HTH

BEARBEITEN: Beachten Sie, dass es möglicherweise unsicher ist, den zurückgegebenen String in eine URL aufzunehmen. Sie sollten es mindestens in HTML codieren, um XSS-Angriffe zu verhindern.

Stefan Haberl
quelle
Wichtige Informationen dazu, Sie können die StringUtils-Klasse / das StringUtils-Paket usw. erhalten. @ commons.apache.org/lang/download_lang.cgi
cV2
Sie haben nie Slugify
Star
@Star slugifyist eine öffentliche Dienstprogrammmethode, die Sie im Rest Ihres Codes verwenden können.
Stefan Haberl
2

Nun, hier ist eine Lösung, die ich gefunden habe, aber ich hoffe, es gibt eine elegantere ...

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 endet mit dem gewünschten Ergebnis ...

Epaga
quelle
1
Die Tatsache, dass Ihre Variable String benannt ist, namedeutet darauf hin, dass es sich nicht um eine große Zeichenfolge handelt. Aber in Fällen, in denen es groß wird (ein paar Tausend Zeichen), würde ich wie jetzt mit der for-Anweisung weitermachen.
Bart Kiers
1

Möglicherweise möchten Sie zuerst die Akzente und diakritischen Zeichen entfernen und dann bei jeder Zeichenposition prüfen, ob die "vereinfachte" Zeichenfolge ein ASCII-Buchstabe ist. Wenn dies der Fall ist, muss die ursprüngliche Position Wortzeichen enthalten. Wenn nicht, kann sie entfernt werden.

István
quelle
Die Klasse java.text.Normalizer wird vor der Android-API-Stufe 9 nicht unterstützt. Wenn Ihre App also mit der API-Stufe 8 kompatibel sein muss (13% aller Geräte laut Googles Android-Dashboard), ist diese Methode nicht praktikabel
Giorgio Barchiesi,