I'm trying to replace some text in a file and the string contains a file path which requires some back slashes, normally using "\" works fine and produces a single \ on the output but my current code is not outputting any backslashes
String newConfig = readOld().replaceAll(readOld(),"[HKEY_CURRENT_USER\\Software\\xxxx\\xxxx\\Config]");
The "\" starts an escape sequence,
A character preceded by a backslash (\) is an escape sequence and has special meaning to the compiler.
So, (ludicrously perhaps)
String old = readOld();
String newConfig = old.replaceAll(old,
"[HKEY_CURRENT_USER\\\\Software\\\\xxxx\\\\xxxx\\\\Config]");
Or,
String old = readOld();
char backSlash = '\\';
String newConfig = old.replaceAll(old,
"[HKEY_CURRENT_USER" + backSlash + backSlash + "Software"
+ backSlash + backSlash + "xxxx"
+ backSlash + backSlash + "xxxx"
+ backSlash + backSlash + "Config]");
You should use replace here as it may possible your readOld() method may be having some special characters (i.e +,*,. etc.) which are reserved in regExp so better to use replace.(As replaceAll may throw Exception for invalid regular Expression)
String newConfig = readOld().replace(readOld(),"replacement");
As here it seems you are replacing whole String why not just assign String directly to newConfig
From JavaDoc for replaceAll
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
So either go For \\\\ (As suggested by Elliott Frinch) in String or use replace.
Related
This question already has answers here:
How to escape text for regular expression in Java?
(8 answers)
Closed 2 years ago.
I have a snippet
public static void main(String[] args) {
// replacement text
String replacement = "Not Set";
// text
String text = "Item A \\(XXX\\) Lock"; // text is "Item A\(XXX\)Lock"
String regex = "\\(XXX\\)"; // regex is "\(XXX\)"
// result text
String resultText = text.replaceAll(regex, replacement);
System.out.println("Result text: " + resultText);
}
resultText is "Item A \(XXX\) Lock" -> I can not replace "\(XXX\)" to "Not Set".
Please help me if you know about this problem.
The regex language has its own escape sequence on top of the Java string literal escape sequence. So to match a backslash, you need \\ in the regex and thus \\\\ in the Java string literal
In this case you could also use Pattern.quote
text.replaceAll(Pattern.quote(regex), Matcher.quoteReplacement(replacement));
The characters \, ( and ) all have a special meaning when used in a regular expression. But you don't want to use them with their special meaning, which means you have to escape them in the regular expression. That means preceding them with \, to tell the regular expression processor not to invoke the special meaning of those characters.
In other words, a regular expression containing \\ will match \, a regular expression containing
\( will match ( and so on.
To match \(XXX\), the regular expression you want will be \\\(XXX\\\) - see how there's an extra \ for each \, ( and ) that you want to match. But to specify this regular expression in a Java String literal, you need to write \\ in place of each \. That is, you need to write
"\\\\\\(XXX\\\\\\)". There are six \ characters in each little run of them.
String regex = "\\\\\\(XXX\\\\\\)";
String resultText = text.replaceAll(regex, replacement);
I can replace dollar signs by using Matcher.quoteReplacement. I can replace words by adding boundary characters:
from = "\\b" + from + "\\b";
outString = line.replaceAll(from, to);
But I can't seem to combine them to replace words with dollar signs.
Here's an example. I am trying to replace "$temp4" (NOT $temp40) with "register1".
String line = "add, $temp4, $temp40, 42";
String to = "register1";
String from = "$temp4";
String outString;
from = Matcher.quoteReplacement(from);
from = "\\b" + from + "\\b"; //do whole word replacement
outString = line.replaceAll(from, to);
System.out.println(outString);
Outputs
"add, $temp4, $temp40, 42"
How do I get it to replace $temp4 and only $temp4?
Use unambiguous word boundaries, (?<!\w) and (?!\w), instead of \b that are context dependent:
from = "(?<!\\w)" + Pattern.quote(from) + "(?!\\w)";
See the regex demo.
The (?<!\w) is a negative lookbehind that fails the match if there is a non-word char immediately to the left of the current location and (?!\w) is a negative lookahead that fails the match if there is a non-word char immediately to the right of the current location. The Pattern.quote(from) is necessary to escape any special chars in the from variable.
See the Java demo:
String line = "add, $temp4, $temp40, 42";
String to = "register1";
String from = "$temp4";
String outString;
from = "(?<!\\w)" + Pattern.quote(from) + "(?!\\w)";
outString = line.replaceAll(from, to);
System.out.println(outString);
// => add, register1, $temp40, 42
Matcher.quoteReplacement() is for the replacement string (to), not the regex (from). To include a string literal in the regex, use Pattern.quote():
from = Pattern.quote(from);
$ has special meaning in regex (it means “end of input”). To remove any special meaning from characters in your target, wrap it in regex quote/unquote expressions \Q...\E. Also, because $ is not ”word” character, the word boundary won’t wiork, so use look arounds instead:
line = line.replaceAll("(?<!\\S)\\Q" + from + "\\E(?![^ ,])", to);
Normally, Pattern.quote is the way to go to escape characters that may be specially interpreted by the regex engine.
However, the regular expression is still incorrect, because there is no word boundary before the $ in line; space and $ are both non-word characters. You need to place the word boundary after the $ character. There is no need for Pattern.quote here, because you're escaping things yourself.
String from = "\\$\\btemp4\\b";
Or more simply, because you know there is a word boundary between $ and temp4 already:
String from = "\\$temp4\\b";
The from variable can be constructed from the expression to replace. If from has "$temp4", then you can escape the dollar sign and add a word boundary.
from = "\\" + from + "\\b";
Output:
add, register1, $temp40, 42
I would like to use regex in order to replace '"' value but only if this char isnt followed by backslash
e.g.
\"Hello\" -> \"Hello\"
"Hello" -> 'Hello'
i used the following statement but in deletes the previous char of the '"'
[^\\])\"
how do i do that in java?
Use a negative lookbehind assertion.
string.replaceAll("(?<!\\\\)\"", "'");
In java regex \\\\ matches a single backslash. So (?<!\\\\)\" matches the double quotes only if it isn't preceded by a backslash.
String s1 = "\\\"Hello\\\"";
String s2 = "\"Hello\"";
System.out.println(s1.replaceAll("(?<!\\\\)\"", "'"));
System.out.println(s2.replaceAll("(?<!\\\\)\"", "'"));
Output:
\"Hello\"
'Hello'
I'm getting message from other program where some characters are changed:
\n (enter) -> #
(hash) # -> \#
\ -> \\\\
When I'm trying to reverse these change with my code it's not working, probably of that
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.
This is my code:
public String changeChars(final String message) {
String changedMessage = message;
changedMessage = changePattern(changedMessage, "[^\\\\][#]", "\n");
changedMessage = changePattern(changedMessage, "([^\\\\][\\\\#])", "#");
changedMessage = changePattern(changedMessage, "[\\\\\\\\\\\\\\\\]", "\\\\");
return changedMessage;
}
private String changePattern(final String message, String patternString, String replaceString) {
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(message);
return matcher.replaceAll(replaceString);
}
I assume that your encoding method works like this.
replace all \ with \\\\
mark originally placed # as \#
now since we know that all originally placed # have \ before it we can use it to mark new lines \n with #.
Code for that could be something like
data = data.replace("\\", "\\\\\\\\");
data = data.replace("#", "\\#");
data = data.replace("\n", "#");
To reverse this operation we need to start from the end (form last replacement)
We will replace all # that don't have \ before it with new line \n marks (if we started with 2nd replacement \# -> # we wouldn't know later which of # ware replacements of \n).
After that we can safely replace \# with # (this way we will get rid of additional \ that wasn't in original String and it won't bother our last replacement step).
and lastly we replace \\\\ with \.
Here is how we can do it.
//your previous regex [^\\\\][#] describes "any character that is not \ and #
//but since we don't want to include that additional non `\` mark while replacing
//we should use negative look-behind mechanism "(?<!prefix)"
data = data.replaceAll("(?<!\\\\)#", "\n");
//now since we got rid of additional "#" its time to replace `\#` to `#`
data = data.replace("\\#", "#");
//and lastly `\\\\` to `\`
data = data.replace("\\\\\\\\", "\\");
I'm writing code that's supposed to remove actual line breaks from a block of text and replace them with the String "\n". Then, when the String is read at another time, it should replace the line breaks (in other words, search for all "\n" and insert \n. However, while the first conversion works fine, it's not doing the latter. It seems as though the second replace is doing nothing. Why?
The replace:
theString.replaceAll(Constants.LINE_BREAK, Constants.LINE_BREAK_DB_REPLACEMENT);
The re-replace:
theString.replaceAll(Constants.LINE_BREAK_DB_REPLACEMENT, Constants.LINE_BREAK);
The constants:
public static final String LINE_BREAK = "\n";
public static final String LINE_BREAK_DB_REPLACEMENT = "\\\\n";
In String.replaceAll(regex, replacement), both the regex string and replacement string treat backslash as an escape character:
regex represents a regular expression, which escapes a backslash as \\
replacement is a replacement string, which also escapes backslashes:
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; see Matcher.replaceAll.
This means backslashes must be escaped in both parameters. Further, string constants also use backslash as an escape character, so backslashes in string constants passed to the method must be double-escaped (see also this question).
This works fine for me:
// Replace newline with "\n"
theString.replaceAll("\\n", "\\\\n");
// Replace "\n" with newline
theString.replaceAll("\\\\n","\n");
You can also use the Matcher.quoteReplacement() method to treat the replacement string as a literal:
// Replace newline with "\n"
theString.replaceAll("\\n", Matcher.quoteReplacement("\\n"));
// Replace "\n" with newline
theString.replaceAll("\\\\n",Matcher.quoteReplacement("\n"));
You dont need four backslashes in the last replaceAll() method call.
This seems to work fine for me
String str = "abc\nefg\nhijklm";
String newStr = str.replaceAll("\n", "\\\\n");
String newnewStr = newStr.replaceAll("\\\\n", "\n");
The output is:
abc
efg
hijklm
abc\nefg\nhijklm
abc
efg
hijklm
Which I think is what you expected.