用实际值替换字符串中的shell环境变量

时间:2017-07-05 10:01:41

标签: java replace

我正在用Java阅读一个属性文件。

Properties myProp = new Properties();
InputStream in = new FileInputStream(pathOfPropertyFile);
myProp.load(in);
in.close();

属性文件中的值引用了Linux shell变量。 例如,属性文件中的条目可能如下所示:

DATA_PATH=/data/${PROJECT}/${YEAR}${MONTH}${DAY}

我必须从java执行一个shell脚本,因此我有 ProcessBuilder 实例以及下面给出的环境变量(envMap):

List<String> command = new ArrayList<String>();
command.add(actualCommand);
command.add(param1);
command.add(param2);
ProcessBuilder processBuilder = new ProcessBuilder(command);
Map<String, String> envMap = processBuilder.environment();

envMap包含我需要的环境变量以及我不需要的超过一百(> 100)个其他环境变量。

我想从属性值字符串${USER}中替换${PROJECT}"/home/${USER}/${PROJECT}/data"等,并使用shell中的实际值。

我会考虑迭代Map作为最后一个选项(因为Map有100到200个要迭代的元素),因为它不是一种有效的方法。

请告知一些方法,它将从字符串中获取由大括号括起的环境变量,这样我就可以直接使用Map的get()并替换。或者,任何更好的方法都是最受欢迎的。

注意:提供的引用(Replace String values with value in Hash Map使我的问题看起来重复)并不是我的最佳选择。

2 个答案:

答案 0 :(得分:4)

如果您愿意使用外部库,来自apache-commons的StrSubstitutor将完全按照您的意愿执行:

public static void main(String[] args) {
    String input = "DATA_PATH=/data/${PROJECT}/${YEAR}${MONTH}${DAY}";
    Map<String, String> env = new HashMap<>();
    env.put("PROJECT", "myProject");
    env.put("YEAR", "2017");
    env.put("MONTH", "7");
    env.put("DAY", "5");
    env.put("OTHER_VALUE", "someOtherValue");
    System.out.println(StrSubstitutor.replace(input, env));
}

输出:

DATA_PATH=/data/myProject/201775

它还有directly replace system properties的方法,无需显式地图。

(对于非外部库方法,请参阅vefthym's answer

答案 1 :(得分:0)

我不确定它是否有效,但我希望有人可以编辑以使其正常工作,或者至少你可以获得逻辑并使其自行运行:

command = command.replaceAll("\\$\\{(.*?)\\}", envMap.get("$1"));

在这里,我假设command是一个String(不是List),并且Map中存在所有环境变量(否则你应该检查null并根据需要处理这种情况)。

一点解释:

这个正则表达式正在寻找模式&#34; $ {something}&#34;并用envMap.get("something")替换它。在这个例子中,我们使用括号标记&#34;某些东西&#34;作为一个群体,然后可以缩回为&#34; $ 1&#34; (因为我们只有一个组,即只有一组括号)。 问号&#39;?&#39;这里的非贪婪算子意味着停止在最小的正则表达式匹配(否则它将找到第一个&#34; $ {&#34;直到最后&#34;}&#34;的单一匹配。