简体   繁体   English

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM