Это должно сделать работу: заменить:
(^|[^\\])(\\{2})*(?=\$)
со всем сопоставленным текстом (кроме заглядывания), затем следует \\
.
Иллюстрация в Perl:
$ perl -pe 's,(^|[^\\])(\\{2})*(?=\$),$&\\,g'
"$ Find the $ to \$ escape \\$ or not \\\$ escape \\\\$ like here $" # in...
"\$ Find the \$ to \$ escape \\\$ or not \\\$ escape \\\\\$ like here \$" # out
"\$ Find the \$ to \$ escape \\\$ or not \\\$ escape \\\\\$ like here \$" # in...
"\$ Find the \$ to \$ escape \\\$ or not \\\$ escape \\\\\$ like here \$" # out
В Java полное совпадение текста - $0
. Пример кода:
// package declaration skipped
import java.util.regex.Pattern;
public final class TestMatch
{
private static final Pattern p
= Pattern.compile("(^|[^\\\\])(\\\\{2})*(?=\\$)");
public static void main(final String... args)
{
String input = "\"$ Find the $ to \\$ escape \\\\$ or not \\\\\\$ "
+ "escape \\\\\\\\$ like here $\"";
System.out.println(input);
// Apply a first time
input = p.matcher(input).replaceAll("$0\\\\");
System.out.println(input);
// Apply a second time: the input should not be altered
input = p.matcher(input).replaceAll("$0\\\\");
System.out.println(input);
System.exit(0);
}
}
Выход:
"$ Find the $ to \$ escape \\$ or not \\\$ escape \\\\$ like here $"
"\$ Find the \$ to \$ escape \\\$ or not \\\$ escape \\\\\$ like here \$"
"\$ Find the \$ to \$ escape \\\$ or not \\\$ escape \\\\\$ like here \$"
Небольшое объяснение по поводу используемого регулярного выражения в следующем порядке:
# begin regex:
( # start group
^ # find the beginning of input,
| # or
[^\\] # one character which is not the backslash
) # end group
# followed by
( # start group
\\{2} # exactly two backslashes
) # end group
* # zero or more times
# and at that position,
(?= # begin lookahead
\$ # find a $
) # end lookahead
# end regex
Чтобы быть действительно полным, вот позиции, в которых движок регулярных выражений найдет соответствующий текст (обозначенный <>
) и положение курсора (обозначенное |
):
# Before first run:
|"$ Find the $ to \$ escape \\$ or not \\\$ escape \\\\$ like here $"
# First match
"<>|$ Find the $ to \$ escape \\$ or not \\\$ escape \\\\$ like here $"
# Second match
"$ Find the <>|$ to \$ escape \\$ or not \\\$ escape \\\\$ like here $"
# Third match
"$ Find the $ to \$ escape <\\>|$ or not \\\$ escape \\\\$ like here $"
# Fourth match
"$ Find the $ to \$ escape \\$ or not \\\$ escape <\\\\>|$ like here $"
# From now on, there is no match