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