[英]Replace shell environment variables in a string with actual values
I am reading a property file in Java. 我正在读取Java中的属性文件。
Properties myProp = new Properties();
InputStream in = new FileInputStream(pathOfPropertyFile);
myProp.load(in);
in.close();
The values in the property file have references to Linux shell variables. 属性文件中的值引用了Linux Shell变量。 For example, an entry in the property file might look like: 例如,属性文件中的条目可能如下所示:
DATA_PATH=/data/${PROJECT}/${YEAR}${MONTH}${DAY}
I have to execute a shell script from java and so I have ProcessBuilder instance and also the environment variables ( envMap
as given below): 我必须从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();
The envMap
has the environment variables I require along with over one hundred (> 100) other environment variables which I do not require. envMap
具有我需要的环境变量以及一百个(> 100)我不需要的其他环境变量。
I want to replace the ${USER}
, ${PROJECT}
,etc., from the property-value string "/home/${USER}/${PROJECT}/data"
with actual values from the shell. 我想用外壳程序中的实际值替换属性值字符串"/home/${USER}/${PROJECT}/data"
的${USER}
, ${PROJECT}
等。
I would consider iterating the Map as the last option(as the Map has between 100 and 200 elements to iterate) as it is not an efficient approach. 我认为将Map作为最后一个选项进行迭代(因为Map具有要迭代的100到200个元素),因为它不是一种有效的方法。
Please advise some approach that will fetch the environment variable enclosed by braces from the string, so that I can directly use the get() of the Map and replace. 请提供一些建议,该方法将从字符串中获取由大括号括起来的环境变量,以便我可以直接使用Map的get()并进行替换。 Or, any better approaches are most welcome. 或者,最好欢迎任何更好的方法。
Note: The reference offered ( Replace String values with value in Hash Map that made my question to look duplicate) is not the best fit in my case. 注意:提供的引用( 用哈希表中的值替换字符串值使我的问题看上去重复)不是我的最佳选择。
If you are open to using an external library, StrSubstitutor
from apache-commons will do exactly what you want: 如果您愿意使用外部库, StrSubstitutor
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));
}
Output: 输出:
DATA_PATH=/data/myProject/201775
It also has a method to directly replace system properties without the need for an explicit map. 它还具有一种无需显式映射即可直接替换系统属性的方法。
(for a non-external-library approach see vefthym's answer ) (对于非外部库方法,请参见vefthym的答案 )
I am not sure if it works, but I hope someone can edit to make it work, or at least you get the logic and make it work on your own: 我不确定它是否有效,但是我希望有人可以对其进行编辑以使其起作用,或者至少您能理解并使其独立工作:
command = command.replaceAll("\\$\\{(.*?)\\}", envMap.get("$1"));
Here, I am assuming that command
is a String (not a List) and that all environment variables exist in your Map (otherwise you should check for null and handle this case as you wish). 在这里,我假设command
是一个字符串(不是列表),并且所有环境变量都存在于您的Map中(否则,您应该检查null并根据需要处理这种情况)。
A bit of an explanation: 有点解释:
this regex is looking for the pattern "${something}" and replaces it with envMap.get("something")
. 此正则表达式正在寻找模式“ $ {something}”,并将其替换为envMap.get("something")
。 In this example, we use parentheses to mark "something" as a group, which can then be retracted as "$1" (since we have only one group, ie, only one set of parentheses). 在此示例中,我们使用括号将“某物”标记为一组,然后可以将其缩回为“ $ 1”(因为我们只有一组,即只有一组括号)。 The question mark '?' 问号“?” is the non-greedy operator here meaning to stop at the smallest possible regex match (otherwise it would find a singe match for the first "${" until the last "}". 是此处的非贪婪运算符,表示在最小的正则表达式匹配处停止(否则,它将找到第一个“ $ {”直到最后一个“}”的单一匹配)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.