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 <==== ??? } }
Advertisement
Answer
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