如何在Java中replace不区分大小写的子string

在String中使用replace(CharSequence target, CharSequence replacement)方法replace(CharSequence target, CharSequence replacement) ,如何使目标不区分大小写?

例如,它现在的工作方式是:

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

我怎样才能让它如此replace(或者如果有一个更合适的方法)是不区分大小写的,这样两个例子都返回“Bar”?

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

输出:

 Bar 

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

不像其他方法那样优雅,但它很坚实,易于遵循,尤其是, 对于Java新手来说 有一件事让我了解了String类,它是这样的:它已经存在很长时间了,虽然它支持用regexp进行全局replace,并且用Strings(通过CharSequences)进行全局replace,但是最后没有一个简单的布尔参数:'isCaseInsensitive'。 实际上,你认为只要加上一个小小的开关,就可以避免所有给初学者造成的麻烦。 现在在JDK 7上,String还不支持这一点!

无论如何,我会停止抱怨。 对于每个特别喜欢Java的人来说,这里是你的剪切和粘贴的精神 。 正如我所说,不是那么优雅,不会赢得任何漂亮的编码奖品,但它的工作和可靠。 任何意见,随时作出贡献。 (是的,我知道,StringBuffer可能是pipe理两个string突变线的更好select,但是交换技术很容易。)

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

正则expression式pipe理起来相当复杂,因为某些字符是保留的:例如, "foo.bar".replaceAll(".")会产生一个空string,因为点意味着“任何东西”如果您只想replace该点应该表示为参数"\\."

一个更简单的解决scheme是使用StringBuilder对象来search和replace文本。 它需要两个:一个包含小写版本的文本,而另一个包含原始版本。 search是在小写内容上执行的,检测到的索引也会replace原文。

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

我喜欢smas的使用replaceAll与正则expression式的答案 。 如果您要多次进行相同的replace,则预编译一次正则expression式是有意义的:

 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("БАД");