replaceFirst , Why can't special symbols be replaced?
System.out.println(cal); // 1 * 1 1 <==== ???
package com;
import org.apache.commons.lang.StringUtils;
public class Test {
public static void main(String[] args) {
String cal = "[aaa] * [aaa] [bbb]";
int cnt = StringUtils.countMatches(cal, "[");
String delStr = "";
for (int i = 0; i < cnt; i ) {
delStr = cal.substring(cal.indexOf("["), cal.indexOf("]") 1);
cal = cal.replaceFirst("[" delStr "]", "1");
}
System.out.println(cal); // 1 * 1 1 <==== ???
}
}
CodePudding user response:
Special symbols which are used in the regular expressions need to be either escaped using \
or entire expression should be treated as a string literal with the help of Pattern.quote
which basically surrounds the regex with the pair of \Q
and \E
.
Also, in the presented code delStr
would include the pair of the square brackets, thus the replacement should occur for the regexp [[aaa]]
, and unexpected match -- first a
in the first occurrence of [aaa]
-- is found and replaced for such pattern instead of implied replacement. Then for the following iterations the cal
looks like [1aa] * [aaa] [bbb]
and cal.indexOf("[")
bring the same first occurrence several times.
So, the following escape of the special symbols described above works fine:
String delStr = "";
for (int i = 0; i < cnt; i ) {
delStr = cal.substring(cal.indexOf("["), cal.indexOf("]") 1);
cal = cal.replaceFirst("\\Q" delStr "\\E", "1"); // literal mode
// or cal = cal.replaceFirst(Pattern.quote(delStr), "1");
}
Also, this solution may be refactored to completely get rid of the loop and String::indexOf
/ String::replaceFirst
methods, because the implied result means that all the substrings between [
and ]
including the brackets should be replaced with 1
, that is, String::replaceAll
would do the entire job:
cal = cal.replaceAll("\\[[^]]*\\]", "1"); // 1 * 1 1