Korzystając z metody replace(CharSequence target, CharSequence replacement)
w String, w jaki sposób mogę sprawić, aby w miejscu docelowym nie była rozróżniana wielkość liter?
Na przykład sposób, w jaki to działa teraz:
String target = "FooBar";
target.replace("Foo", "") // would return "Bar"
String target = "fooBar";
target.replace("Foo", "") // would return "fooBar"
Jak sprawić, by zamień (lub jeśli istnieje bardziej odpowiednia metoda) nie rozróżniał wielkości liter, tak aby oba przykłady zwracały „Bar”?
target.replaceAll("(?i)"+Pattern.quote("foo"), "");
Jeśli nie przejmujesz się wielkością liter, być może nie ma znaczenia, czy zwraca wszystkie wielkie litery:
target.toUpperCase().replace("FOO", "");
źródło
Może nie tak elegancki jak inne podejścia, ale jest dość solidny i łatwy do naśladowania, szczególnie. dla osób nowszych w Javie. Jedną rzeczą, która mnie przekonuje o klasie String, jest to: istnieje od bardzo dawna i chociaż obsługuje globalne zastępowanie wyrażeniami regularnymi i globalne zastępowanie ciągami (przez CharSequences), to ostatnie nie ma prostego parametru boolowskiego : „isCaseInsensitive”. Naprawdę, można by pomyśleć, że wystarczy dodać ten jeden mały przełącznik, aby uniknąć wszystkich problemów, które jego brak powoduje szczególnie dla początkujących. Teraz w JDK 7, String nadal nie obsługuje tego jednego małego dodatku!
W każdym razie, przestanę się skarżyć. Dla wszystkich, zwłaszcza nowszych w Javie, oto twoja deus ex machina do wycinania i wklejania . Jak powiedziałem, nie jest tak elegancki i nie wygra żadnych nagród za zgrabne kodowanie, ale działa i jest niezawodny. Wszelkie komentarze, nie krępuj się. (Tak, wiem, StringBuffer jest prawdopodobnie lepszym wyborem do zarządzania dwiema liniami mutacji ciągu znaków, ale dość łatwo jest zamienić techniki).
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; }
źródło
Wyrażenia regularne są dość skomplikowane w zarządzaniu ze względu na fakt, że niektóre znaki są zarezerwowane: na przykład
"foo.bar".replaceAll(".")
tworzy pusty ciąg, ponieważ kropka oznacza „cokolwiek”. Jeśli chcesz zamienić tylko punkt, należy wskazać go jako parametr"\\."
.Prostszym rozwiązaniem jest użycie obiektów StringBuilder do wyszukiwania i zastępowania tekstu. Potrzeba dwóch: jeden, który zawiera tekst zapisany małymi literami, a drugi zawiera wersję oryginalną. Wyszukiwanie odbywa się na małych literach, a wykryty indeks zastąpi również oryginalny tekst.
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", "*")); } }
źródło
W przypadku znaków innych niż Unicode:
String result = Pattern.compile("(?i)препарат", Pattern.UNICODE_CASE).matcher(source).replaceAll("БАД");
źródło
org.apache.commons.lang3.StringUtils:
public static String replaceIgnoreCase (String tekst, String searchString, String zamiennik)
Wielkość liter nieuwzględniająca zastępuje wszystkie wystąpienia String w innym String.
źródło
Po prostu uprość to bez bibliotek innych firm:
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));
źródło
Lubię Lifting „s odpowiedź , która wykorzystuje
replaceAll
z wyrażenia regularnego. Jeśli zamierzasz wielokrotnie wykonywać tę samą zamianę, warto raz wstępnie skompilować wyrażenie regularne: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")); } }
źródło