如何在Java中替换不区分大小写的文字子串

问题描述 投票:111回答:8

在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”?

java string replace substring case-insensitive
8个回答
246
投票
String target = "FOOBar";
target = target.replaceAll("(?i)foo", "");
System.out.println(target);

输出:

Bar

值得一提的是,replaceAll将第一个参数视为正则表达式模式,这可能会导致意外结果。要解决这个问题,请按照评论中的建议使用Pattern.quote


11
投票

不像其他方法那样优雅,但它非常可靠,易于理解,尤其是。适合刚接触Java的人。让我了解String类的一件事是:它已经存在了很长时间,虽然它支持全局替换regexp和全局替换字符串(通过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;
}

8
投票

如果你不关心案例,那么你或许它并不重要,如果它返回所有大写:

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

8
投票

正则表达式管理相当复杂,因为某些字符是保留的:例如,"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", "*"));
    }
}

3
投票

我喜欢smasanswer,它使用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
投票

对于非Unicode字符:

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

1
投票

org.apache.commons.lang3.StringUtils:

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

大小写不敏感地替换另一个String中出现的所有String。


0
投票

只需在没有第三方库的情况下简化:

    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));
© www.soinside.com 2019 - 2024. All rights reserved.