I have the following code:
public class Test {
public static void main(String[] args) {
String path = "${file.path}/fld/";
String realValue = "C:\\path\\smtg\\";
String variable = "${file.path}";
path = path.replaceAll("\\$\\{" + variable.substring(2, variable.length() - 1) + "\\}", realValue);
System.out.println(path);
}
}
which gives me the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: character to be escaped is missing
at java.util.regex.Matcher.appendReplacement(Matcher.java:809)
at java.util.regex.Matcher.replaceAll(Matcher.java:955)
at java.lang.String.replaceAll(String.java:2223)
at testCode.Test.main(Test.java:9)
I already find some question about this problem, but still I don't understand this error. Can someone explain me what's going on?
I know that replace
would work well, but unfortunately my collegues do not want to modify this code. So I need to know the exact problem to deliver a solution, because in other installations it works.
For your particular case you need to do the following:
public static void main(String[] args) {
String path = "${file.path}/fld/";
String realValue = "C:\\\\path\\\\smtg\\\\"; //Notice the double slashes here
String variable = "${file.path}";
path = path.replaceAll("\\$\\{" + variable.substring(2, variable.length() - 1) + "\\}", realValue);
System.out.println(path);
}
And now for the explanation. When you do a replaceAll
the second part of a string is also interpreted by Java and has special characters like \
and $
. So in order to add a \ in the string you need to escape it and it becomes \\
and if you want to use it in the resulting string literal you need to escape each one of them so it becomes "\\\\"
If you check java doc on the replaceAll method in a matcher: https://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html#replaceAll%28java.lang.String%29
Note that backslashes (\) and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string. Dollar signs may be treated as references to captured subsequences as described above, and backslashes are used to escape literal characters in the replacement string.
A simpler solution in your case would be to use replace
instead of replaceAll
since your pattern is pretty straightforward and you don't need a regex support, you can just match against a full string "${file.path}"
path = path.replace("${file.path}", realValue);
//or even
path = path.replace(variable, realValue);
ReplaceAll is treating it's input as a regular expression. There are some valid escape expressions in regex, like \w
for a word character or \s
for any whitespace. If file.path
is a Windows path containing \
it may well have invalid escape sequences. Any any case it will not have the meaning you intend it to have.
The other occurrences that worked were they on a unix like environment? (unix, linux, os-x etc) if so it could of worked because those environments use /
for path separators.
Before calling replaceAll
you could try
variable = variable.replace("\\", "\\\\"); // to escape any \ in path.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With