我正在尝试编写一个函数来在java中执行环境变量的替换。所以如果我有一个看起来像这样的字符串:
用户$ {USERNAME}的APPDATA路径是 $ {APPDATA}。
我希望结果是:
用户msmith的APPDATA路径是 C:\ Users \用户msmith \应用程序数据\漫游
到目前为止,我的破坏实现看起来像这样:
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;
}
使用上面的示例文本,matcher.matches()
返回false。但是,如果我的示例文本为${APPDATA}
则可行。
有人可以帮忙吗?
答案 0 :(得分:14)
您不想使用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);
}
答案 1 :(得分:12)
如果您不想自己编写代码,那么Apache Commons Lang库就有一个名为StrSubstitutor的类。它就是这样做的。
答案 2 :(得分:2)
public static String expandEnvVars(String text) {
Map<String, String> envMap = System.getenv();
for (Entry<String, String> entry : envMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
text = text.replaceAll("\\$\\{" + key + "\\}", value);
}
return text;
}
答案 3 :(得分:2)
基于可接受的答案,但没有嵌套模式替换。
还支持默认值和env名称中的下划线:${env-var[:default]}
static String substituteEnvVars(String text) {
StringBuffer sb = new StringBuffer();
String pattern = "\\$\\{([A-Za-z0-9_]+)(?::([^\\}]*))?\\}";
Pattern expr = Pattern.compile(pattern);
Matcher matcher = expr.matcher(text);
while (matcher.find()) {
final String varname = matcher.group(1);
String envValue = System.getenv(varname);
if (envValue == null) {
envValue = matcher.group(2);
if (envValue == null)
envValue = "";
}
matcher.appendReplacement(sb, envValue);
}
matcher.appendTail(sb);
return sb.toString();
}
另外,变量被完全替换一次。具有VAR = $ {X}和X = x的文本“ $ {VAR} $ {X}”将返回“ $ {X} x”而不是“ xx”。
答案 4 :(得分:2)
我已经使用@ lexx9999代码,并对其进行了一些微调,以使用StringBuilder
来处理Map和环境变量。
private final static Pattern ENV_VAR_PATTERN =
Pattern.compile("\\$\\{([A-Za-z0-9_.-]+)(?::([^\\}]*))?\\}");
/**
* Handle "hello ${var}", "${var:default}" formats for environ variable expansion.
*/
public static String substituteEnvVars(String text) {
return substituteEnvVars(text, System.getenv());
}
/**
* Handle "hello ${var}", "${var:default}", find var in replaceMap replace value.
*/
public static String substituteEnvVars(String text, Map<String, ?> replaceMap) {
StringBuilder sb = new StringBuilder();
Matcher matcher = ENV_VAR_PATTERN.matcher(text);
int index = 0;
while (matcher.find()) {
sb.append(text, index, matcher.start());
String var = matcher.group(1);
Object obj = replaceMap.get(var);
String value;
if (obj != null)
value = String.valueOf(obj);
else {
// if no env variable, see if a default value was specified
value = matcher.group(2);
if (value == null)
value = "";
}
sb.append(value);
index = matcher.end();
}
sb.append(text, index, text.length());
return sb.toString();
}
答案 5 :(得分:0)
除非你只是想学习如何从头开始构建东西,否则你不应该真的费心实现自己的模板引擎 - 有multitudes already available。
一个非常好的是FreeMarker(有Java API)。这是tutorial。