从包含同一文件中的嵌套变量的文件中读取变量

从包含同一文件中的嵌套变量的文件中读取变量

我希望你一切都好。

我有一点困惑...

我有一个像这样的文件:

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) 。

相关内容