从 bash 读取 java .properties 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1682442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:39:27  来源:igfitidea点击:

Reading java .properties file from bash

bashscriptingproperties

提问by Alex N.

I am thinking of using sed for reading .properties file, but was wondering if there is a smarter way to do that from bash script?

我正在考虑使用 sed 来读取 .properties 文件,但想知道是否有更聪明的方法可以从 bash 脚本中做到这一点?

采纳答案by Joshua Davis

The solutions mentioned above will work for the basics. I don't think they cover multi-line values though. Here is an awk program that will parse Java properties from stdin and produce shell environment variables to stdout:

上面提到的解决方案将适用于基础知识。我不认为它们涵盖了多行值。这是一个 awk 程序,它将从 stdin 解析 Java 属性并将 shell 环境变量生成到 stdout:

BEGIN {
    FS="=";
    print "# BEGIN";
    n="";
    v="";
    c=0; # Not a line continuation.
}
/^\#/ { # The line is a comment.  Breaks line continuation.
    c=0;
    next;
}
/\$/ && (c==0) && (NF>=2) { # Name value pair with a line continuation...
    e=index(
cat myproperties.properties | awk -f readproperties.awk > temp.sh
source temp.sh
,"="); n=substr(
# Usage: get_property FILE KEY
function get_property
{
    grep "^=" "" | cut -d'=' -f2
}
,1,e-1); v=substr(
while(<STDIN>) {
   ($prop,$val)=split(/[=: ]/, $_, 2);
   # and do stuff for each prop/val
}
,e+1,length(
line_a : "ABC"
line_b = Line\
         With\ 
         Breaks!
line_c = I'm unquoted :(
) - e - 1); # Trim off the backslash. c=1; # Line continuation mode. next; } /^[^\]+\$/ && (c==1) { # Line continuation. Accumulate the value. v= "" v substr(
line_a="ABC"
line_b=`echo -e "Line\nWith\nBreaks!"`
line_c="I'm unquoted :("
,1,length(
# Usage: _getvar VARIABLE_NAME [sourcefile...]
# Echos the value that would be assigned to VARIABLE_NAME
_getvar() {
  local VAR=""
  shift
  awk -v Q="'" -v QQ='"' -v VAR="$VAR" '
    function loc(text) { return index(
dbUrlFile=$(grep database.url.file etc/zocalo.conf | sed -e "s/.*: //" -e "s/#.*//")
, text) } function unquote(d) {
    PROPERTIES_FILE=project.properties
function source_property {
  local name=
  eval "$name=\"$(sed -n '/^'"$name"'=/,/^[A-Z]\+_*[A-Z]*=/p' $PROPERTIES_FILE|sed -e 's/^'"$name"'=//g' -e 's/"/\"/g'|head -n -1)\""
}

    source_property 'SOME_PROPERTY'
= substr(##代码##, eq+2) d; print substr(##代码##, 1, loc(d)-1) } { sub(/^[ \t]+/, ""); eq = loc("=") } substr(##代码##, 1, eq-1) != VAR { next } # assignment is not for VAR: skip loc("=" QQ) == eq { unquote(QQ); exit } loc("=" Q) == eq { unquote( Q); exit } { print substr(, eq + 1); exit } ' "$@" }
)-1); next; } ((c==1) || (NF>=2)) && !/^[^\]+\$/ { # End of line continuation, or a single line name/value pair if (c==0) { # Single line name/value pair e=index(##代码##,"="); n=substr(##代码##,1,e-1); v=substr(##代码##,e+1,length(##代码##) - e); } else { # Line continuation mode - last line of the value. c=0; # Turn off line continuation mode. v= "" v ##代码##; } # Make sure the name is a legal shell variable name gsub(/[^A-Za-z0-9_]/,"_",n); # Remove newlines from the value. gsub(/[\n\r]/,"",v); print n "=\"" v "\""; n = ""; v = ""; } END { print "# END"; }

As you can see, multi-line values make things more complex. To see the values of the properties in shell, just source in the output:

如您所见,多行值使事情变得更加复杂。要在 shell 中查看属性的值,只需在输出中使用 source:

##代码##

The variables will have '_' in the place of '.', so the property some.property will be some_property in shell.

变量将使用 '_' 代替 '.',因此属性 some.property 在 shell 中将是 some_property。

If you have ANT properties files that have property interpolation (e.g. '${foo.bar}') then I recommend using Groovy with AntBuilder.

如果您的 ANT 属性文件具有属性插值(例如“${foo.bar}”),那么我建议将 Groovy 与 AntBuilder 一起使用。

Here is my wiki page on this very topic.

这是我关于这个主题的 wiki 页面

回答by Dmitry Trofimov

This would probably be the easiest way: grep + cut

这可能是最简单的方法:grep + cut

##代码##

回答by Shawn

I wrote a script to solve the problem and put it on my github.

我写了一个脚本来解决这个问题,放在我的github上。

See properties-parser

属性解析器

回答by Matt Hurne

One option is to write a simple Java program to do it for you - then run the Java program in your script. That might seem silly if you're just reading properties from a single properties file. However, it becomes very useful when you're trying to get a configuration value from something like a Commons Configuration CompositeConfigurationbacked by properties files. For a time, we went the route of implementing what we needed in our shell scripts to get the same behavior we were getting from CompositeConfiguration. Then we wisened up and realized we should just let CompositeConfigurationdo the work for us! I don't expect this to be a popular answer, but hopefully you find it useful.

一种选择是编写一个简单的 Java 程序来为您执行此操作 - 然后在您的脚本中运行该 Java 程序。如果您只是从单个属性文件中读取属性,这可能看起来很愚蠢。但是,当您尝试从诸如CompositeConfiguration由属性文件支持的 Commons 配置之类的东西获取配置值时,它变得非常有用。有一段时间,我们采用了在 shell 脚本中实现我们需要的方法,以获得与从CompositeConfiguration. 然后我们清醒了,意识到我们应该让CompositeConfiguration我们为我们做工作!我不希望这是一个受欢迎的答案,但希望你觉得它有用。

回答by Brian Agnew

In Perl:

在 Perl 中:

##代码##

Not tested, and should be more tolerant of leading/trailing spaces, comments etc., but you get the idea. Whether you use Perl (or another language) over sedis really dependent upon what you want to do with the properties once you've parsed them out of the file.

未经测试,应该更容忍前导/尾随空格、注释等,但您明白了。您是否使用 Perl(或其他语言)sed实际上取决于您将属性从文件中解析出来后想要对它们做什么。

Note that (as highlighted in the comments) Java properties files can have multiple forms of delimiters(although I've not seen anything used in practice other than colons). Hence the split uses a choice of characters to split upon.

请注意(如注释中突出显示的那样)Java 属性文件可以有多种形式的分隔符(尽管除了冒号之外,我还没有看到任何其他形式的分隔符)。因此,拆分使用选择的字符进行拆分。

Ultimately, you may be better off using the Config::Propertiesmodule in Perl, which is built to solve this specific problem.

最终,您最好使用Perl 中的Config::Properties模块,它是为解决这个特定问题而构建的。

回答by PaoloVictor

If you want to use sed to parse -any- .properties file, you may end up with a quite complex solution, since the format allows line breaks, unquoted strings, unicode, etc: http://en.wikipedia.org/wiki/.properties

如果您想使用 sed 来解析 -any- .properties 文件,您可能会得到一个非常复杂的解决方案,因为该格式允许换行、未加引号的字符串、unicode 等:http: //en.wikipedia.org/wiki /。特性

One possible workaround would using java itself to preprocess the .properties file into something bash-friendly, then source it. E.g.:

一种可能的解决方法是使用 java 本身将 .properties 文件预处理为 bash 友好的文件,然后获取它。例如:

.properties file:

.properties 文件:

##代码##

would be turned into:

会变成:

##代码##

Of course, that would yield worse performance, but the implementation would be simpler/clearer.

当然,这会产生更差的性能,但实现会更简单/更清晰。

回答by Adam Katz

This is a solution that properly parses quotes and terminates at a space when not given quotes. It is safe: no evalis used.

这是一个正确解析引号并在未给出引号时以空格终止的解决方案。它是安全的:没有eval使用。

I use this code in my .bashrc and .zshrc for importing variables from shell scripts:

我在 .bashrc 和 .zshrc 中使用此代码从 shell 脚本导入变量:

##代码##

This saves the desired variable name and then shifts the argument array so the rest can be passed as files to awk.

这将保存所需的变量名称,然后移动参数数组,以便其余的可以作为文件传递给awk.

Because it's so hard to call shell variables and refer to quote characters inside awk, I'm defining them as awkvariables on the command line. Qis a single quote (apostrophe) character, QQis a double quote, and VARis that first argument we saved earlier.

因为很难调用 shell 变量并引用里面的引号字符awk,所以我将它们定义为awk命令行上的变量。Q是单引号(撇号)字符,QQ是双引号,VAR是我们之前保存的第一个参数。

For further convenience, there are two helper functions. The first returns the location of the given text in the current line, and the second prints the content between the first two quotes in the line using quote character d(for "delimiter"). There's a stray dconcatenated to the first substras a safety against multi-line strings (see "Caveats" below).

为了进一步方便,有两个辅助函数。第一个返回给定文本在当前行中的位置,第二个使用引号字符d(用于“分隔符”)打印行中前两个引号之间的内容。有一个杂散d连接到第一个substr作为对多行字符串的安全保护(请参阅下面的“注意事项”)。

While I wrote the code for POSIX shell syntax parsing, that appears to only differ from your format by whether there is white space around the asignment. You can add that functionality to the above code by adding sub(/[ \t]*=[ \t]*/, "=");before the sub(…)on awk's line 4 (note: line 1 is blank).

虽然我为 POSIX shell 语法解析编写了代码,但它似乎与您的格式不同,仅在于分配周围是否有空格。您可以通过在 awk 的第 4 行sub(/[ \t]*=[ \t]*/, "=");之前添加来将该功能添加到上述代码中sub(…)(注意:第 1 行为空)。

The fourth line strips off leading white space and saves the location of the first equals sign. Please verify that your awksupports \tas tab, this is not guaranteed on ancient UNIX systems.

第四行去掉前导空白并保存第一个等号的位置。请验证您是否awk支持\t选项卡,这在古老的 UNIX 系统上是不能保证的。

The substrline compares the text before the equals sign to VAR. If that doesn't match, the line is assigning a different variable, so we skip it and move to the next line.

substr行将等号前的文本与 进行比较VAR。如果不匹配,则该行分配了不同的变量,因此我们跳过它并移至下一行。

Now we know we've got the requested variable assignment, so it's just a matter of unraveling the quotes. We do this by searching for the first location of ="(line 6) or ='(line 7) or no quotes (line 8). Each of those lines prints the assigned value.

现在我们知道我们已经获得了请求的变量赋值,所以这只是解开引号的问题。我们通过搜索="(第 6 行)或='(第 7 行)或没有引号(第 8行)的第一个位置来做到这一点。这些行中的每一行都打印分配的值。

Caveats: If there is an escaped quote character, we'll return a value truncated to it. Detecting this is a bit nontrivial and I decided not to implement it. There's also a problem of multi-line quotes, which get truncated at the first line break (this is the purpose of the "stray d" mentioned above). Most solutions on this page suffer from these issues.

警告:如果有转义的引号字符,我们将返回一个截断的值。检测到这一点有点重要,我决定不实施它。还有一个多行引号的问题,它在第一个换行符处被截断(这是d上面提到的“stray ”的目的)。此页面上的大多数解决方案都存在这些问题。

回答by PanCrit

I have some shell scriptsthat need to look up some .properties and use them as arguments to programs I didn't write. The heart of the script is a line like this:

我有一些shell 脚本需要查找一些 .properties 并将它们用作我没有编写的程序的参数。脚本的核心是这样的一行:

##代码##

Effectively, that's grep for the key and filter out the stuff before the colon and after any hash.

实际上,这是键的 grep 并过滤掉冒号之前和任何散列之后的内容。

回答by aizen

I have had some success with

我已经取得了一些成功

##代码##

回答by ghostdog74

if you want to use "shell", the best tool to parse files and have proper programming control is (g)awk. Use sed only simple substitution.

如果您想使用“shell”,解析文件并进行适当编程控制的最佳工具是 (g)awk。仅使用 sed 进行简单替换。