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

139918 次浏览

如果你不在乎大小写,那么你可能不在乎它是否全部返回大写:

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

产出:

Bar

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

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

也许不像其他方法那样优雅,但它相当牢固,容易遵循,尤其是。对于新人来说,爪哇。String 类的一个特点是: 它已经存在很长时间了,虽然它支持使用 regexp 进行全局替换,并支持使用 String 进行全局替换(通过 CharSequences) ,但是它最后没有一个简单的布尔参数: ‘ isCaseInsense’。真的,你可能会认为,只要加上一个小开关,所有的麻烦,它的缺席对初学者造成的特别是可以避免。现在在 JDK7上,String 还是不支持这个小小的添加!

不管怎样,我不抱怨了。对于每一个特别是 Java 新手来说,这里是剪切粘贴的 救世主。正如我所说,没有那么优雅,也不会为您赢得任何圆滑的编码奖,但它工作正常,并且是可靠的。有什么意见,尽管提出来。(是的,我知道,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;
}

我喜欢 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"));
}
}

对于非 Unicode 字符:

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

StringUtils:

Public static String replaceIgnoreCase (字符串文本, 字符串搜索字符串, 字符串替换)

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

只要让它变得简单,不需要第三方库:

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

我知道这是一个老问题了,但是对于 Apache 的 StringUtils,这个问题非常简单:

String target = "FooBar";
StringUtils.replaceIgnoreCase(target , "bar", "");
// Output: Foo

这是 Maven Dep。

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>