在文本中展开环境变量

2022-09-03 09:13:40

我正在尝试编写一个函数来执行java中环境变量的替换。因此,如果我有一个看起来像这样的字符串:

用户 ${USERNAME} 的 APPDATA 路径是 ${APPDATA}。

我希望结果是:

User msmith 的 APPDATA 路径是 C:\Users\msmith\AppData\Roaming。

到目前为止,我破碎的实现看起来像这样:

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;
}

使用上面的示例文本,返回 false。但是,如果我的示例文本,它是否有效。matcher.matches()${APPDATA}

任何人都可以帮忙吗?


答案 1

您不想使用 matchs()。.匹配项将尝试匹配整个输入字符串。

尝试将整个区域与模式进行匹配。

你想要的是.这将匹配您的模式的每个实例。查看 find() 的文档while(matcher.find()) {

在每个匹配项中,将是整个匹配字符串 (),并且将是部分。group 0${appdata}group 1appdata

您的最终结果应如下所示:

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);
}

答案 2

如果你不想自己编写代码,Apache Commons Lang库有一个名为StrSubstitutor的类。它正是这样做的。