在文本中展开环境变量

Mic*_*ith 14 java regex

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

用户$ {USERNAME}的APPDATA路径为$ {APPDATA}.

我希望结果如下:

用户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;
}
Run Code Online (Sandbox Code Playgroud)

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

有人可以帮忙吗?

jjn*_*guy 15

你不想用matches().匹配将尝试匹配整个输入字符串.

尝试将整个区域与模式匹配.

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

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

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

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);
}
Run Code Online (Sandbox Code Playgroud)


rfe*_*eak 13

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


小智 5

以下替代方案无需求助于库即可达到预期效果:

  • 在启动时读取一次环境变量的映射
  • on callexpandEnvVars()将带有潜在占位符的文本作为参数
  • 然后该方法遍历环境变量的映射,一次一个条目,获取条目的键和值
  • 并尝试用 替换${<key>}文本中出现的任何<value>,从而将占位符扩展到它们在环境中的当前值
    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;
    }
Run Code Online (Sandbox Code Playgroud)

  • @Dave C String #replaceAll 在幕后使用正则表达式 (3认同)
  • +1。这个比图书馆更紧凑。在带有路径的 Windows 下工作时,我更喜欢 `String value = entry.getValue().replace('\\', '/');` 因为否则“\”字符被解释为导致无效路径的转义 (2认同)