I'm trying to write a function to perform substitutions of environment variables in java. So if I had a string that looked like this:
User ${USERNAME}'s APPDATA path is ${APPDATA}.
I want the result to be:
User msmith's APPDATA path is C:\Users\msmith\AppData\Roaming.
So far my broken implementation looks like this:
public static String expandEnvVars(String text) {
Map<String, String> envMap = System.getenv();
String pattern = "\\$\\{([A-Za-z0-9]+)\\}";
Pattern expr = Pattern.compile(pattern);
Matcher matcher = expr.matcher(text);
if (matcher.matches()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
String envValue = envMap.get(matcher.group(i).toUpperCase());
if (envValue == null) {
envValue = "";
} else {
envValue = envValue.replace("\\", "\\\\");
}
Pattern subexpr = Pattern.compile("\\$\\{" + matcher.group(i) + "\\}");
text = subexpr.matcher(text).replaceAll(envValue);
}
}
return text;
}
Using the above sample text, matcher.matches()
returns false. However if my sample text, is ${APPDATA}
it works.
Can anyone help?
You don't want to use matches()
. Matches will try to match the entire input string.
Attempts to match the entire region against the pattern.
What you want is while(matcher.find()) {
. That will match each instance of your pattern. Check out the documentation for find()
.
Within each match, group 0
will be the entire matched string (${appdata}
) and group 1
will be the appdata
part.
Your end result should look something like:
String pattern = "\\$\\{([A-Za-z0-9]+)\\}";
Pattern expr = Pattern.compile(pattern);
Matcher matcher = expr.matcher(text);
while (matcher.find()) {
String envValue = envMap.get(matcher.group(1).toUpperCase());
if (envValue == null) {
envValue = "";
} else {
envValue = envValue.replace("\\", "\\\\");
}
Pattern subexpr = Pattern.compile(Pattern.quote(matcher.group(0)));
text = subexpr.matcher(text).replaceAll(envValue);
}
If you don't want to write the code for yourself, the Apache Commons Lang library has a class called StrSubstitutor. It does exactly this.
The following alternative has the desired effect without resorting to a library:
expandEnvVars()
takes the text with potential placeholders as an argument${<key>}
in the text with <value>
, thereby expanding the placeholders to their current values in the environment private static Map<String, String> envMap = System.getenv();
public static String expandEnvVars(String text) {
for (Entry<String, String> entry : envMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
text = text.replaceAll("\\$\\{" + key + "\\}", value);
}
return text;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With