我希望你一切都好。
我有一点困惑...
我有一个像这样的文件:
var1:value1
var2:value2
...
varn:blabla/$var2/blabla
当我读取文件时,没有问题,我可以获取所有行,并实例化所有变量。
简而言之,这就是我在函数中所做的事情:
while IFS=":" read -r f1 f2
do
if [ ! -z $f1 ] && [ ! -z $f2 ]; then
f2=eval $f2
export $f1=$f2
fi
done < $fileName
它运作良好,除了varn...
我明白了blabla/$var2/blabla
而不是:
blabla/value2/blabla...
这使得我的脚本无法启动命令,因为 varn 应该是路径。
真正的参数文件是:
<deleted some parameters>
version:1.7.0
MongoInstall:/apps/deliverable_${version}/mongo
在执行过程中我得到:
+ export 'MongoInstall=/ec/local/nasstat/apps/deliverable_${version}/mongo'
+ MongoInstall='/ec/local/nasstat/apps/deliverable_${version}/mongo'
...
进而...
+ '/apps/deliverable_${version}/mongo/installation_mongo_1.7.0.sh' env stop
./mongotransfer.sh: line 54: /apps/deliverable_${version}/mongo/installation_mongo_1.7.0.sh: No such file or directory
虽然我希望得到:
/apps/deliverable_1.7.0/mongo/installation_mongo_1.7.0.sh
谢谢
答案1
如果可以选择切换到zsh
,您可以这样做:
set -o extendedglob -o nounset
unset MongoInstall
while IFS= read -r line; do
[[ $line = (#b)([[:IDENT:]]##):(*) ]] &&
: ${(P)match[1]::=${(e)match[2]}}
done < parameter-file
printf 'MongoInstall="%s"\n' $MongoInstall
当心这个e
标志,就像你eval
会很乐意评估那里的代码一样。例如,如果参数文件包含var=$(reboot)
,则会重新启动。
更安全的方法是手动进行扩展:
MongoInstall=$(
perl -wlne '
if (/^(\w+):(.*)/) {
$var = $1; $value = $2;
$value =~ s/\$\{(\w+)\}/$var{$1}/g;
$var{$var} = $value;
}
END {print $var{MongoInstall}}' < parameter-file
)
或者与以下内容相同zsh
:
set -o extendedglob -o nounset
typeset -A vars
while IFS= read -r line; do
if [[ $line = (#b)([[:IDENT:]]##):(*) ]]; then
var=$match[1] value=$match[2]
value=${value//(#b)\${([[:IDENT:]]##)}/$vars[$match[1]]}
vars[$var]=$value
fi
done < parameter-file
print -r -- $vars[MongoInstall]
在 中bash
,也许您打算写:
while IFS=: read -r f1 f2
do
if [ -n "$f1" ] && [ -n "$f2" ]; then
eval "$f1=\"$f2\""
fi
done < parameter-file
假设 的行parameter-file
不包含"
s 并且不以 结尾:
。它不会尝试检查是否$f1
包含有效的变量名称或一般<contents-of-f1>="<contents-of-f2>"
形式的有效bash
代码。
您的代码中的f2=eval $f2
没有意义,它尝试在其环境中运行存储在$f2
(受 split+glob 限制,未引用)中的命令。f2=eval
export
除了污染稍后运行的命令的环境之外,使用这些变量也没有任何作用。
在 中将参数扩展不加引号也是不正确的bash
,尤其是[ -z
( [ ! -z x ]
is [ -n x ]
btw) 。