Replacing Environment Variables in a Properties File

Replacing environment variables in a properties file

sed 's/$HOSTNAME/myhost/g;s/$unconfigured//g' yourfile.txt > another_file.txt

update:

Based on updates in your question, this won't be a good solution.

update2 :

This is based on an answer to a related question. I've hacked at it (I'm unfamiliar with perl) to remove undefined vars.

perl -p -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : $&/eg; s/\$\{([^}]+)\}//eg' yourfile.txt

Should work for any input text file, however you will need to define vars using the ${...} format which simplifies the string matching.

(rant regarding the evilness of eval moved to a separate post so as not to confuse readers)

How to substitute the environment variable in the parameter defined in the .properties file

Thank you @Stefan D. Your response introduced me to variable interpolation and I was able to do further research on it.

A simple addition of the variable ENV_NAME=qa2 in the properties file did not help me with replacing the environment name in the URLS. On reading further I understood that it isnt possible substitute the placeholder. Standard properties files are just key-value pairs.

OscarRyz's answer helped me in figuring out how to do it.

If it helps anyone out there who is new to the world of coding,
In the class where the properties file is loaded and read I declared
private XProperties configFile = new XProperties();

I created another class for XProperties and copied in the code from GitHub XProperties

Regarding application.properties file and environment variable

You can put environment variables in your properties file, but Java will not automatically recognise them as environment variables and therefore will not resolve them.

In order to do this you will have to parse the values and resolve any environment variables you find.

You can get at environment variables from Java using various methods. For example: Map<String, String> env = System.getenv();

There's a basic tutorial here: http://java.sun.com/docs/books/tutorial/essential/environment/env.html

Hope that's of some help.

Resolve environment variables of property file Java ResourceBundle

The simplest variant based on the Regex engine would be:

private static final Pattern VARIABLE = Pattern.compile("\\$\\{(.*?)\\}");
public String getString() {
return VARIABLE.matcher(props.getProperty(value))
.replaceAll(mr -> Matcher.quoteReplacement(System.getenv(mr.group(1))));
}

This replaces all occurrences of ${VAR} with the result of looking up System.getenv("VAR"). If the string contains no variable references, the original string is returned. It does, however, not handle absent variables. If you want to handle them (in a different way than failing with a runtime exception), you have to add the policy to the function.

E.g. the following code keeps variable references in their original form if the variable has not been found:

public String getString() {
return VARIABLE.matcher(props.getProperty(value))
.replaceAll(mr -> {
String envVal = System.getenv(mr.group(1));
return Matcher.quoteReplacement(envVal != null? envVal: mr.group());
});
}

replaceAll(Function<MatchResult, String>) requires Java 9 or newer. For previous versions, you’d have to implement such a replacement loop yourself. E.g.

public String getString() {
String string = props.getProperty(value);
Matcher m = VARIABLE.matcher(string);
if(!m.find()) return string;
StringBuilder sb = new StringBuilder();
int last = 0;
do {
String replacement = System.getenv(m.group(1));
if(replacement != null) {
sb.append(string, last, m.start()).append(replacement);
last = m.end();
}
} while(m.find());
return sb.append(string, last, string.length()).toString();
}

This variant does not use appendReplacement/appendTail which is normally used to build such loops, for two reasons.

  • First, it provides more control over how the replacement is inserted, i.e. by inserting it literally via append(replacement) we don’t need Matcher.quoteReplacement(…).
  • Second, we can use StringBuilder instead of StringBuffer which might also be more efficient. The Java 9 solution uses StringBuilder under the hood, as support for it has been added to appendReplacement/appendTail in this version too. But for previous versions, StringBuilder can only be used when implementing the logic manually.

Note that unlike the replaceAll variant, the case of absent variables can be handled simpler and more efficient with a manual replacement loop, as we can simply skip them.


You said you don’t want to change the initialization code, but I still recommend bringing it into a more idiomatic form, i.e.

private static void initEnvironment(Properties props, String bundleName) {
ResourceBundle rb = ResourceBundle.getBundle(bundleName);
for(Enumeration<String> enu = rb.getKeys(); enu.hasMoreElements(); ) {
String key = enu.nextElement();
String value = rb.getString(key);
props.setProperty(key, value);
}
}

In the end, it’s still doing the same. But iteration loops should be using for, to keep initialization expression, loop condition and fetching the next element as close as possible. Further, there is no reason to use Enumeration<?> with a type cast when you can use Enumeration<String> in the first place. And don’t declare variables outside the necessary scope. And there’s no reason to pre-initialize them with null.



Related Topics



Leave a reply



Submit