[java] Java에서 대소 문자를 구분하지 않는 리터럴 하위 문자열을 바꾸는 방법

replace(CharSequence target, CharSequence replacement)String 의 메소드 를 사용하여 대상을 대소 문자를 구분하지 않게하려면 어떻게해야합니까?

예를 들어, 현재 작동 방식 :

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주석에서 제안한대로 사용 하십시오.


답변

대소 문자를 신경 쓰지 않으면 모든 대문자를 반환하는지 여부는 중요하지 않습니다.

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


답변

아마도 다른 접근 방식만큼 우아하지는 않지만 매우 견고하고 따르기 쉽습니다. Java를 처음 사용하는 사람들을 위해. String 클래스에 대해 한 가지 사실은 다음과 같습니다. 매우 오랫동안 주변에 있었고 regexp로 전역 대체와 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;
}


답변

정규식은 일부 문자가 예약되어 있기 때문에 관리하기가 매우 복잡합니다. 예를 들어 "foo.bar".replaceAll(".")점은 “anything”을 의미하기 때문에 빈 문자열을 생성합니다. 교체하려는 경우 점만 매개 변수로 표시해야합니다 "\\.".

더 간단한 해결책은 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 result = Pattern.compile("(?i)препарат",
Pattern.UNICODE_CASE).matcher(source).replaceAll("БАД");


답변

org.apache.commons.lang3.StringUtils :

공개 정적 문자열 replaceIgnoreCase (문자열 텍스트, 문자열 검색 문자열, 문자열 대체)

대소 문자를 구분하지 않으면 다른 문자열 내에서 모든 문자열이 대체됩니다.


답변

나는 정규식으로 사용 하는 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"));
    }
}