我正在用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使我的问题看起来重复)并不是我的最佳选择。
答案 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;的单一匹配。