Ersetzen von Literal-Teilzeichenfolgen ohne Berücksichtigung der Groß- und Kleinschreibung in Java


130

replace(CharSequence target, CharSequence replacement)Wie kann ich mithilfe der Methode in String die Groß- und Kleinschreibung des Ziels nicht berücksichtigen?

Zum Beispiel, wie es jetzt funktioniert:

String target = "FooBar";
target.replace("Foo", "") // would return "Bar"

String target = "fooBar";
target.replace("Foo", "") // would return "fooBar"

Wie kann ich dafür sorgen, dass das Ersetzen (oder wenn es eine geeignetere Methode gibt) die Groß- und Kleinschreibung nicht berücksichtigt, sodass beide Beispiele "Bar" zurückgeben?

Antworten:


284
String target = "FOOBar";
target = target.replaceAll("(?i)foo", "");
System.out.println(target);

Ausgabe:

Bar

Erwähnenswert ist, dass replaceAlldas erste Argument als Regex-Muster behandelt wird, was zu unerwarteten Ergebnissen führen kann. Um dies zu lösen, verwenden Sie auch Pattern.quotewie in den Kommentaren vorgeschlagen.


1
Was ist, wenn das Ziel $ oder diakritische Zeichen wie á enthält?
Stracktracer

3
Ich meine zwei Dinge: 1. "blÁÜ123" .replaceAll ("(? I) bláü") ersetzt nichts. 2. "Satz! Ende" .replaceAll ("(? I) Satz.") Ersetzt möglicherweise mehr als erwartet.
Stracktracer

1
Sie können einen String nicht so einfach in einen regulären Ausdruck verwandeln. Es ist im Allgemeinen nicht korrekt, es funktioniert nur für bestimmte Fälle.
Danubian Sailor

19
Verwenden Sie Pattern.quote (), um die Suchzeichenfolge vor der Interpretation als regulärer Ausdruck zu schützen. Dieser Doe-Rotz behebt die oben aufgeführten Unicode-Macken, sollte jedoch für grundlegende Zeichensätze in Ordnung sein. zB target.replaceAll("(?i)"+Pattern.quote("foo"), "");
Jeff Adamson

1
Nur um sicher zu gehen. Pattern.quote ("foo") ist nicht erforderlich, wenn die Zeichenfolge "foo" ist, oder? Nur wenn es etwas ausgefalleneres ist, oder?
ed22

10

Wenn Sie sich nicht für case interessieren, ist es Ihnen vielleicht egal, ob alle Groß- und Kleinschreibung zurückgegeben werden:

target.toUpperCase().replace("FOO", "");

Sie können das Gebietsschema auch an toUpperCase (Gebietsschema) übergeben, wenn Sie mit Zeichen wie á arbeiten.
Rob

10

Vielleicht nicht so elegant wie andere Ansätze, aber es ist ziemlich solide und leicht zu befolgen, insb. für Leute, die neu in Java sind. Eine Sache, die mich an der String-Klasse interessiert, ist folgende: Es gibt sie schon sehr lange und obwohl sie ein globales Ersetzen durch regulären Ausdruck und ein globales Ersetzen durch Strings (über CharSequences) unterstützt, hat das letzte keinen einfachen booleschen Parameter : 'isCaseInsensitive'. Wirklich, Sie hätten gedacht, dass durch das Hinzufügen dieses einen kleinen Schalters all die Probleme, die seine Abwesenheit insbesondere für Anfänger verursacht, hätten vermieden werden können. Jetzt auf JDK 7 unterstützt String diese eine kleine Ergänzung immer noch nicht!

Na ja, ich werde aufhören zu greifen. Für alle, die besonders neu in Java sind, ist hier Ihr Deus ex machina zum Ausschneiden und Einfügen . Wie gesagt, nicht so elegant und bringt Ihnen keine tollen Codierungspreise ein, aber es funktioniert und ist zuverlässig. Bei Kommentaren können Sie gerne einen Beitrag leisten. (Ja, ich weiß, StringBuffer ist wahrscheinlich die bessere Wahl für die Verwaltung der Mutationslinien mit zwei Zeichenfolgen, aber es ist einfach genug, die Techniken auszutauschen.)

public String replaceAll(String findtxt, String replacetxt, String str, 
        boolean isCaseInsensitive) {
    if (str == null) {
        return null;
    }
    if (findtxt == null || findtxt.length() == 0) {
        return str;
    }
    if (findtxt.length() > str.length()) {
        return str;
    }
    int counter = 0;
    String thesubstr = "";
    while ((counter < str.length()) 
            && (str.substring(counter).length() >= findtxt.length())) {
        thesubstr = str.substring(counter, counter + findtxt.length());
        if (isCaseInsensitive) {
            if (thesubstr.equalsIgnoreCase(findtxt)) {
                str = str.substring(0, counter) + replacetxt 
                    + str.substring(counter + findtxt.length());
                // Failing to increment counter by replacetxt.length() leaves you open
                // to an infinite-replacement loop scenario: Go to replace "a" with "aa" but
                // increment counter by only 1 and you'll be replacing 'a's forever.
                counter += replacetxt.length();
            } else {
                counter++; // No match so move on to the next character from
                           // which to check for a findtxt string match.
            }
        } else {
            if (thesubstr.equals(findtxt)) {
                str = str.substring(0, counter) + replacetxt 
                    + str.substring(counter + findtxt.length());
                counter += replacetxt.length();
            } else {
                counter++;
            }
        }
    }
    return str;
}

Diese Methode ist äußerst langsam, da ihre Komplexität O (size_str * size_findtext) ist
Mladen Adamovic

9

Reguläre Ausdrücke sind recht komplex zu verwalten, da einige Zeichen reserviert sind: "foo.bar".replaceAll(".")Erzeugt beispielsweise eine leere Zeichenfolge, da der Punkt "alles" bedeutet. Wenn Sie nur den Punkt ersetzen möchten, sollte er als Parameter angegeben werden "\\.".

Eine einfachere Lösung besteht darin, StringBuilder-Objekte zum Suchen und Ersetzen von Text zu verwenden. Es dauert zwei: eine, die den Text in Kleinbuchstaben enthält, während die zweite die Originalversion enthält. Die Suche wird für den Inhalt in Kleinbuchstaben durchgeführt, und der erkannte Index ersetzt auch den Originaltext.

public class LowerCaseReplace 
{
    public static String replace(String source, String target, String replacement)
    {
        StringBuilder sbSource = new StringBuilder(source);
        StringBuilder sbSourceLower = new StringBuilder(source.toLowerCase());
        String searchString = target.toLowerCase();

        int idx = 0;
        while((idx = sbSourceLower.indexOf(searchString, idx)) != -1) {
            sbSource.replace(idx, idx + searchString.length(), replacement);
            sbSourceLower.replace(idx, idx + searchString.length(), replacement);
            idx+= replacement.length();
        }
        sbSourceLower.setLength(0);
        sbSourceLower.trimToSize();
        sbSourceLower = null;

        return sbSource.toString();
    }


    public static void main(String[] args)
    {
        System.out.println(replace("xXXxyyyXxxuuuuoooo", "xx", "**"));
        System.out.println(replace("FOoBaR", "bar", "*"));
    }
}

1
Funktioniert super! Beachten Sie, dass "Ziel" nicht null sein darf. Das Löschen von sbSourceLower sollte nicht mehr erforderlich sein.
Msteiger

Danke für die prägnante Lösung und danke an @msteiger für die Korrektur. Ich frage mich, warum niemand einer berühmten Bibliothek wie Guava, Apache Commons usw. eine ähnliche Lösung hinzugefügt hat.
Yetanothercoder

4

Für Nicht-Unicode-Zeichen:

String result = Pattern.compile("(?i)препарат", 
Pattern.UNICODE_CASE).matcher(source).replaceAll("БАД");

4

org.apache.commons.lang3.StringUtils:

public static String replaceIgnoreCase (String-Text, String searchString, String-Ersatz)

Groß- und Kleinschreibung wird unabhängig voneinander durch alle Vorkommen eines Strings in einem anderen String ersetzt.


3

Ich mag die Antwort von smas , die mit einem regulären Ausdruck verwendet wird. Wenn Sie den gleichen Ersatz mehrmals durchführen, ist es sinnvoll, den regulären Ausdruck einmal vorkompilieren:replaceAll

import java.util.regex.Pattern;

public class Test { 

    private static final Pattern fooPattern = Pattern.compile("(?i)foo");

    private static removeFoo(s){
        if (s != null) s = fooPattern.matcher(s).replaceAll("");
        return s;
    }

    public static void main(String[] args) {
        System.out.println(removeFoo("FOOBar"));
    }
}

3

Machen Sie es sich einfach ohne Bibliotheken von Drittanbietern:

    final String source = "FooBar";
    final String target = "Foo";
    final String replacement = "";
    final String result = Pattern.compile(target, Pattern.LITERAL | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE).matcher(source)
.replaceAll(Matcher.quoteReplacement(replacement));
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.