This is currently the only solution able to work with multiple shielded \ per line:
String regex = input.replaceAll("\\G((?:[^\\\\*]|\\\\[\\\\*])*)[*]", "$1.*");
How it works
Let print the regex line to look at the actual line processed by the regex engine:
\G((?:[^\\*]|\\[\\*])*)[*]
((?:[^\\*]|\\[\\*])*) matches a sequence of characters, not \ or * , or escape sequences \\ or \* . We match all the characters that we donβt want to touch, and put them in the capture group so that we can return it.
In the above sequence, an unshielded asterisk follows, as described in [*] .
To make sure we donβt βjumpβ when the regular expression cannot match unescaped * , \G used to make sure that the next match can only start at the beginning of a line, or from which the last match ends.
Why such a long solution? . The look-behind construct needs to check whether the number of consecutive \ preceding * odd or even Java regex is not officially supported. Therefore, we need to use the string from left to right, taking into account the escape sequences, until we encounter unescaped * and replace it with .* .
Testing program
String inputs[] = { "toto*", "\\*toto", "\\\\*toto", "*toto", "\\\\\\\\*toto", "\\\\*\\\\\\*\\*\\\\\\\\*"}; for (String input: inputs) { String regex = input.replaceAll("\\G((?:[^\\\\*]|\\\\[\\\\*])*)[*]", "$1.*"); System.out.println(input); System.out.println(Pattern.compile(regex)); System.out.println(); }
Output example
toto* toto.* \*toto \*toto \\*toto \\.*toto *toto .*toto \\\\*toto \\\\.*toto \\*\\\*\*\\\\* \\.*\\\*\*\\\\.*