我正在考虑使用sed来读取.properties文件,但是想知道是否有更聪明的方法可以从bash脚本中执行此操作?
答案 0 :(得分:26)
这可能是最简单的方法:grep + cut
# Usage: get_property FILE KEY
function get_property
{
grep "^$2=" "$1" | cut -d'=' -f2
}
答案 1 :(得分:15)
上述解决方案适用于基础知识。我不认为它们涵盖多行值。这是一个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($0,"=");
n=substr($0,1,e-1);
v=substr($0,e+1,length($0) - e - 1); # Trim off the backslash.
c=1; # Line continuation mode.
next;
}
/^[^\\]+\\$/ && (c==1) { # Line continuation. Accumulate the value.
v= "" v substr($0,1,length($0)-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($0,"=");
n=substr($0,1,e-1);
v=substr($0,e+1,length($0) - e);
} else { # Line continuation mode - last line of the value.
c=0; # Turn off line continuation mode.
v= "" v $0;
}
# 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";
}
如您所见,多行值使事情变得更加复杂。要查看shell中属性的值,只需在输出中输入:
cat myproperties.properties | awk -f readproperties.awk > temp.sh
source temp.sh
变量的'。'代替'。',因此属性some.property将在shell中为some_property。
如果您有具有属性插值的ANT属性文件(例如'$ {foo.bar}'),那么我建议将Groovy与AntBuilder一起使用。
答案 2 :(得分:9)
我编写了一个脚本来解决问题并将其放在我的github上。
答案 3 :(得分:4)
一种选择是编写一个简单的Java程序来为您完成 - 然后在脚本中运行Java程序。如果您只是从单个属性文件中读取属性,那可能看起来很愚蠢。但是,当您尝试从属性文件支持的Commons Configuration CompositeConfiguration
获取配置值时,它变得非常有用。有一段时间,我们在shell脚本中实现了我们需要的路径,以获得我们从CompositeConfiguration
获得的相同行为。然后我们明智地意识到我们应该让CompositeConfiguration
为我们做好工作!我不认为这是一个受欢迎的答案,但希望你发现它很有用。
答案 4 :(得分:1)
Perl:
while(<STDIN>) {
($prop,$val)=split(/[=: ]/, $_, 2);
# and do stuff for each prop/val
}
未经测试,应该更能容忍前导/尾随空格,评论等,但您明白了。是否使用Perl(或其他语言)而不是sed
实际上取决于您在将属性解析出文件后要对属性执行的操作。
请注意(在评论中突出显示)Java属性文件可以有multiple forms of delimiters(虽然我没有看到除了冒号之外的任何实践)。因此,拆分使用选择的字符进行拆分。
最终,您可能最好使用Perl中的Config::Properties模块,它是为解决此特定问题而构建的。
答案 5 :(得分:1)
如果你想使用sed来解析-any- .properties文件,你可能会得到一个非常复杂的解决方案,因为格式允许换行符,不带引号的字符串,unicode等:http://en.wikipedia.org/wiki/.properties
一种可能的解决方法是使用java本身将.properties文件预处理为bash-friendly,然后获取它。 E.g:
.properties文件:
line_a : "ABC"
line_b = Line\
With\
Breaks!
line_c = I'm unquoted :(
会变成:
line_a="ABC"
line_b=`echo -e "Line\nWith\nBreaks!"`
line_c="I'm unquoted :("
当然,这会产生更糟糕的表现,但实施会更简单/更清晰。
答案 6 :(得分:0)
我有一些shell scripts需要查找一些.properties并将它们用作我没写过的程序的参数。脚本的核心是这样的一行:
dbUrlFile=$(grep database.url.file etc/zocalo.conf | sed -e "s/.*: //" -e "s/#.*//")
实际上,这是密钥的grep,并在冒号之前和任何哈希之后过滤掉东西。
答案 7 :(得分:0)
如果你想使用“shell”,解析文件和正确编程控制的最佳工具是(g)awk。使用sed只是简单的替换。
答案 8 :(得分:0)
我有时只是将属性文件发送到bash脚本中。这将导致在脚本中使用文件中的名称和内容设置环境变量。也许这对你来说已经足够了。如果你必须做一些“真正的”解析,当然这不是一种方法。
答案 9 :(得分:0)
decl=`ruby -ne 'puts chomp.sub(/=(.*)/,%q{="\1";}).gsub(".","_")' my.properties`
eval $decl
然后,属性'my.java.prop'可以作为$ my_java_prop访问。
这可以用sed或者其他什么来完成,但我最终选择了红宝石用于它的'irb',这对于实验很方便。 这是非常有限的(点应该只在'='之前替换,没有评论处理),但可能是一个起点。
@Daniel,我试图找到它,但是Bash不喜欢变量名中的点。
答案 10 :(得分:0)
我已经取得了一些成功
PROPERTIES_FILE=project.properties
function source_property {
local name=$1
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'
答案 11 :(得分:0)
这是一种解决方案,可以正确地解析引号,并在不提供引号时以空格终止。是安全的:不使用eval
。
我在.bashrc和.zshrc中使用以下代码从shell脚本中导入变量:
# Usage: _getvar VARIABLE_NAME [sourcefile...]
# Echos the value that would be assigned to VARIABLE_NAME
_getvar() {
local VAR="$1"
shift
awk -v Q="'" -v QQ='"' -v VAR="$VAR" '
function loc(text) { return index($0, text) }
function unquote(d) { $0 = substr($0, eq+2) d; print substr($0, 1, loc(d)-1) }
{ sub(/^[ \t]+/, ""); eq = loc("=") }
substr($0, 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($1, eq + 1); exit }
' "$@"
}
这将保存所需的变量名,然后移动参数数组,以便其余部分可以作为文件传递到awk
。
由于很难调用shell变量并引用awk
中的引号字符,因此我在命令行上将它们定义为awk
变量。 Q
是单引号(撇号)字符,QQ
是双引号,而VAR
是我们之前保存的第一个参数。
为进一步方便起见,有两个帮助程序功能。第一个返回给定文本在当前行中的位置,第二个使用引号字符d
(对于“定界符”)在行的前两个引号之间打印内容。有一个流浪d
与第一个substr
串联在一起,以防止出现多行字符串(请参阅下面的“注意事项”)。
虽然我编写了POSIX Shell语法解析的代码,但看起来仅与您的格式有所不同,即作业周围是否有空格。您可以通过在awk的第4行的sub(/[ \t]*=[ \t]*/, "=");
之前添加sub(…)
来将该功能添加到上述代码中(注意:第1行为空白)。
第四行去除前导空白并保存第一个等号的位置。请验证您的awk
是否支持\t
作为标签,在古老的UNIX系统上不能保证。
substr
行将等号之前的文本与VAR
进行比较。如果不匹配,则该行正在分配其他变量,因此我们将其跳过并移至下一行。
现在,我们知道我们已经拥有所请求的变量赋值,因此只需解开引号即可。为此,我们搜索="
(第6行)或='
(第7行)或不加引号(第8行)的第一个位置。这些行中的每一行都会打印分配的值。
注意事项:如果有转义的引号字符,我们将返回一个被截断的值。检测到这一点并不容易,我决定不实施它。还有一个多行引号的问题,该引号在第一个换行符处被截断(这是上面提到的“ stray d
”的目的)。此页面上的大多数解决方案都遇到这些问题。