Regular Expression Conundrum

  • Thread starter robincurts at gmail dot com
  • Start date
R

robincurts at gmail dot com

I won't pretend that I know what I'm doing with regular expressions. I
have a string that I want to take a chunk out and replace it with a
system property. So I might have app.home as a System property with
the value "/opt/application/" and I want to have a method that takes:

"$app.home/config/" and turns it into "/opt/application/config/"

I am not necessarily committed to using a $ like a scripted variable --
I have tried some other things, like @app.home@/config/ and
${app.home}/config/ -- but my regex is never correct. Here is the
test code I was using for the $app.home I was trying.

I hope someone can see something I'm missing.

Cheers,
Robin

public class EnvRE {

String s1 = "this/has/$variables.inside/of/it";
static final String RE = "^(?:.*?)(\\$[\\d\\w\\.]+?)(?:.*?)$";

public EnvRE() {
Pattern p = Pattern.compile(RE);
Matcher m = p.matcher(s1);

System.out.println("ORIGINAL: " + s1);
if (m.find()) {
for (int i = 0; i < m.groupCount(); i++) {
System.out.println("GROUP " + i + ": " + m.group(i));
}
}
}

public static void main(String[] args) {
new EnvRE();
}
}

Here's my output when I run this:

ORIGINAL: this/has/$variables.inside/of/it
GROUP 0: this/has/$variables.inside/of/it
 
J

Jussi Piitulainen

robincurts said:
I have a string that I want to take a chunk out and replace it with
a system property. So I might have app.home as a System property
with the value "/opt/application/" and I want to have a method that
takes:

"$app.home/config/" and turns it into "/opt/application/config/"
....

public class EnvRE {

String s1 = "this/has/$variables.inside/of/it";
static final String RE = "^(?:.*?)(\\$[\\d\\w\\.]+?)(?:.*?)$";

Anchors here are merely redundant - use m.matches() to match the whole
string. No need to escape . inside the character class, and no need
for \d since \w includes it.

The real mistake is the use of +? for the variable name. You want a
maximal match, so use "\\$[\\w.]+" for the variable itself.
if (m.find()) {
for (int i = 0; i < m.groupCount(); i++) {

A second mistake here hides the first mistake: since m.groupCount()
does not include group 0, the loop stops too early. Test for i <=
m.groupCount() instead.
Here's my output when I run this:

ORIGINAL: this/has/$variables.inside/of/it
GROUP 0: this/has/$variables.inside/of/it

With the correct test, you would have seen that group 1 was "$v".

Consider capturing the context parts, too, if you are sure there is at
most one variable:

if (m.matches()) {
s = m.group(1) + fetch(m.group(2)) + m.group(3);
}

If there might be several variables, see the Javadoc for
Matcher.appendReplacement for how to do it with just "\\$[\\w.]" and a
StringBuffer.
 
O

Oliver Wong

robincurts at gmail dot com said:
I won't pretend that I know what I'm doing with regular expressions. I
have a string that I want to take a chunk out and replace it with a
system property. So I might have app.home as a System property with
the value "/opt/application/" and I want to have a method that takes:

"$app.home/config/" and turns it into "/opt/application/config/"

I am not necessarily committed to using a $ like a scripted variable --
I have tried some other things, like @app.home@/config/ and
${app.home}/config/ -- but my regex is never correct. Here is the
test code I was using for the $app.home I was trying.

I hope someone can see something I'm missing.

Cheers,
Robin

public class EnvRE {

String s1 = "this/has/$variables.inside/of/it";
static final String RE = "^(?:.*?)(\\$[\\d\\w\\.]+?)(?:.*?)$";

public EnvRE() {
Pattern p = Pattern.compile(RE);
Matcher m = p.matcher(s1);

System.out.println("ORIGINAL: " + s1);
if (m.find()) {
for (int i = 0; i < m.groupCount(); i++) {
System.out.println("GROUP " + i + ": " + m.group(i));
}
}
}

public static void main(String[] args) {
new EnvRE();
}
}

Here's my output when I run this:

ORIGINAL: this/has/$variables.inside/of/it
GROUP 0: this/has/$variables.inside/of/it

To clarify, do you want to replace only all occurences of "$app.home" by
the value of the app.home property? Or do you want to seek out all "$"
characters, and treat the stuff that comes after it as an environment
variable, and replace all of those by the corresponding values? Depending on
which, the solution may be significantly different.

- Oliver
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top