簡體   English   中英

如何在 Java 中替換不區分大小寫的文字子字符串

[英]How to replace case-insensitive literal substrings in Java

使用String中的replace(CharSequence target, CharSequence replacement) ,如何讓目標不區分大小寫?

例如,它現在的工作方式:

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

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

我怎樣才能讓它替換(或者如果有更合適的方法)不區分大小寫,以便兩個示例都返回“Bar”?

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

輸出:

Bar

值得一提的是, replaceAll將第一個參數視為正則表達式模式,這可能會導致意外結果。 要解決此問題,還可以按照評論中的建議使用Pattern.quote

也許不像其他方法那么優雅,但它非常可靠且易於遵循,尤其是。 對於剛接觸 Java 的人。 讓我了解 String 類的一件事是:它已經存在很長時間了,雖然它支持用正則表達式進行全局替換和用字符串全局替換(通過 CharSequences),但最后一個沒有簡單的布爾參數:'isCaseInsensitive'。 真的,您會認為只要添加一個小開關,就可以避免它的缺失給初學者帶來的所有麻煩。 現在在 JDK 7 上,String仍然不支持這一點添加!

好吧,無論如何,我會停止抱怨。 對於每個人,特別是 Java 新手,這里是你的剪切和粘貼deus ex machina 正如我所說,它沒有那么優雅,也不會為您贏得任何漂亮的編碼獎,但它有效且可靠。 任何評論,請隨時貢獻。 (是的,我知道,StringBuffer 可能是管理兩個字符串突變行的更好選擇,但是交換技術很容易。)

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

如果您不關心大小寫,那么它是否返回全部大寫可能並不重要:

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

由於某些字符被保留,正則表達式管理起來非常復雜:例如, "foo.bar".replaceAll(".")產生一個空字符串,因為點的意思是“任何東西”如果你只想替換該點應表示為參數"\\\\." .

一個更簡單的解決方案是使用 StringBuilder 對象來搜索和替換文本。 它需要兩個:一個包含小寫版本的文本,而第二個包含原始版本。 對小寫內容執行搜索,檢測到的索引也將替換原始文本。

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", "*"));
    }
}

在沒有第三方庫的情況下讓它變得簡單:

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

對於非 Unicode 字符:

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

org.apache.commons.lang3.StringUtils:

public static String replaceIgnoreCase(String text, String searchString, String replacement)

不區分大小寫替換另一個字符串中所有出現的字符串。

我喜歡smas答案,它使用帶有正則表達式的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"));
    }
}
String newstring  = "";
String target2 = "fooBar";
newstring = target2.substring("foo".length()).trim();   
logger.debug("target2: {}",newstring); 
// output: target2: Bar
    
String target3 = "FooBar";
newstring = target3.substring("foo".length()).trim();
logger.debug("target3: {}",newstring); 
// output: target3: Bar

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM