2017-07-05 75 views
1

我正在读取Java中的属性文件。用实际值替换字符串中的shell环境变量

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)其他环境变量,我不需要一起要求。

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

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

请指教一下从字符串中获取由大括号括起来的环境变量的方法,这样我就可以直接使用map的get()和replace。或者,更好的方法是最受欢迎的。

注意:提供的参考文献(Replace String values with value in Hash Map,使我的问题看起来重复)不是最适合我的情况。

+1

您的列表添加到自己'command.add(命令);'?你试图用'envMap'中的值替换'myProp'中的变量名? – SubOptimal

+0

@SubOptimal谢谢你指出错字错误,我纠正它。考虑到Map中元素的数量(100到200之间),迭代Map元素并不是一个好主意。 – Marco99

+0

您是否正在寻找从'“$ {USER}”'获取''USER'''的方法?我不确定你的问题到底是什么。为什么你需要迭代地图? – Marvin

回答

4

如果您打算使用外部图书馆,StrSubstitutor从Apache的公地会做你想要什么:

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

+0

不错的一个。我不知道这个图书馆。 – vefthym

+0

@Marvin这是非常简单直接使用。感谢您的端到端解决方案。 – Marco99

0

我不知道,如果它的工作原理,但我希望有人可以编辑,使其工作,或者至少你的逻辑,并使其对自己的工作:

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

在这里,我假设该command是一个字符串(不是一个列表),并且所有环境变量都存在于您的Map中(否则您应该检查null并根据需要处理这种情况)。

的解释了一下:

这个表达式是寻找模式“$ {}的东西”,并与envMap.get("something")替换它。在这个例子中,我们使用圆括号将“something”标记为一个组,然后可以将其缩回为“$ 1”(因为我们只有一个组,即只有一组括号)。 问号'?'是非贪婪的操作符,这意味着在尽可能小的正则表达式匹配处停止(否则它会找到第一个“$ {”直到最后一个“}”的单匹配匹配)

+1

对envMap.get(“$ 1”)的调用只是简单地将“$ 1”传递给'get'方法。您可能需要使用Matcher来获取'$ {...}'中的实际字符串,然后_then_将其传递给'get'。 –

+0

@KlitosKyriacou非常感谢你,我现在没有时间编辑。 – vefthym

+0

@KlitosKyriacou您可以添加缺少的代码片段或指向我从哪里可以拿起的方法的链接。 – Marco99