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
> 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.
Robin - 19 Apr 2006 20:08 GMT
Very simple and nice. Thanks for your reply Jussi. Works great.
>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
[quoted text clipped - 39 lines]
> 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