Eran Medan
Eran Medan

Reputation: 45725

Replace all spaces in the key of a property file

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:

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="(?&lt;!#[^=]{0,100})(\s)(?=.*=)" replace="\\\\ " ... />

Upvotes: 3

Views: 1466

Answers (4)

Sachin Thapa
Sachin Thapa

Reputation: 3709

You can do following:

  1. Use a FileReader to read each line of the file.
  2. For each line split it by = into two parts using substring
  3. For first part of split apply regular expression
  4. Concatenate first park with second part.

Or 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

Ian Roberts
Ian Roberts

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

Martin Ender
Martin Ender

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.

Working demo.

Upvotes: 2

StormeHawke
StormeHawke

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

Related Questions