Reputation: 45725
I would like to escape all keys that contain spaces in a Java properties file by adding a \
before them
Example input
prop with spaces=value with spaces
#comment should not be replaced
prop_without_spaces=value with spaces 2
Desired output:
prop\ with\ spaces=value with spaces
#comment should not be replaced
prop_without_spaces=value with spaces 2
I know I can replace all spaces with
<replaceregexp byline="true" flags="g" match="\s" replace="\\\\ " file="..."/>
But it renders this result
prop\ with\ spaces=value\ with\ spaces
#comment\ should\ not\ be\ replaced
prop_without_spaces=value\ with\ spaces\ 2
Or I can do something like this ^(([^=])|(\s))*(=.*)
to match the various groups, but then how do I replace all spaces, e.g. how do I reconstruct the result to include only the non spaces?
In other words, given an input as above, how do I do the following pseudo code, in regex:
#
=
sign Is that possible in RegEx in general, and in Java RegEx in particular? (preferably ANT replaceregexp
example)
EDIT: The solution needs to be a RegEx expression, no code can be involved (unfortunately). I know how to solve this using code :) (thanks for the suggestions though), but I'm trying to go for a RegEx solution first (since I'm using ANT, it will require writing a custom task which I try to avoid).
EDIT2 Based on the great answers, here are the working ANT versions:
Using \G
<replaceregexp match="(\\G[^#= ]*) " replace="\1\\\\ " byline="true"... />
Using lookahead
Escaping comments that have =
sign in them
<replaceregexp match="(\s)(?=.*=)" replace="\\\\ " ... />
Using lookahead + lookbehind
Not escaping comment lines at all (overkill I think)
<replaceregexp match="(?<!#[^=]{0,100})(\s)(?=.*=)" replace="\\\\ " ... />
Upvotes: 3
Views: 1466
Reputation: 3709
You can do following:
=
into two parts using substringOr else you can do it in one line using split.
String s = "my name = abc is my name"
System.out.println(s.split("=")[0].replaceAll("\\s", "") + " = " + s.split("=")[1]);
Hoping it helps !!
Upvotes: 0
Reputation: 122364
Not necessarily the most efficient but you could use a match
expression of
\s(?=.*=)
Which would at least restrict it to matching only spaces to the left of the last equal sign on each line (it wouldn't skip comment lines completely but it would only escape spaces in comments that include an equal sign). This may or may not be sufficient depending on whether any of the values contains an equal sign.
Upvotes: 1
Reputation: 44259
I don't about ant, but if it just runs through a simple replaceAll
, then you could make use of the \G
anchor, which ensures that matches are adjacent:
"((?:^|\\G)[^#= ]*) "
And replace that with "$1\\ "
. Initially we can ignore the \\G
alternative. So we simply try to find the start of a line, and then we continue as long as the current character is neither a space, nor starts a comment, nor a value ([^#= ]*
). And then we match a space. Everything in front of the space is captured into group 1, which we write back with $1
, then a backslash, then a space.
Now when the matcher tries to match again, in addition to the start of a string, it can also continue where it left off - which is still a position of interest - in any line before a comment or a value.
Of course, make sure to use the m
modifier to make ^
match the beginning of each line.
Upvotes: 2
Reputation: 6207
I don't know about doing it with a regex, but if you read each line you could do string.replaceAll(" ", "\\ ")
, and to avoid the commented lines:
if(!string.startsWith("#"))
{
string = string.replaceAll(" ", "\\ ");
}
Upvotes: 0