`bash`变量引用未更新

时间:2017-03-27 01:32:05

标签: bash shell

如何在下面的脚本中的多行字符串中正确引用变量?分配MY_INFO=INFO2不会产生所需的更新输出。

示例脚本:

#!/bin/bash

INFO1="output1"
INFO2="output2"
MY_INFO=INFO1

if [ True ]; then
    INFO="
    Here are the test results
    bbb
    ccc
    aaa
    ${!MY_INFO}
    " 
fi

echo "First:"
echo "$INFO"

MY_INFO=INFO2

echo "Second:"
echo "$INFO"

输出:

    First:

    Here are the test results
    bbb
    ccc
    aaa
    output1

    Second:

    Here are the test results
    bbb
    ccc
    aaa
    output1

期望的输出:

    First:

    Here are the test results
    bbb
    ccc
    aaa
    output1

    Second:

    Here are the test results
    bbb
    ccc
    aaa
    output2

3 个答案:

答案 0 :(得分:1)

由于if [ true ]if完全相同,我们可能会省略if ... fi

要获取变量的late evaluation,可能存在危险的eval命令:

#!/bin/bash

INFO1="output1"
INFO2="output2"
MY_INFO=INFO1

INFO="
Here are the test results
bbb
ccc
aaa
\${!MY_INFO}
" 

echo "First:"
eval echo \""$INFO"\"

MY_INFO=INFO2

echo "Second:"
eval echo \""$INFO"\"

输出:

First:

Here are the test results
bbb
ccc
aaa
output1

Second:

Here are the test results
bbb
ccc
aaa
output2

答案 1 :(得分:1)

您的INFO字符串在第二次调用时不会再次重新评估,您可以将其转换为函数以接受变量输入,例如......

#!/bin/bash

INFO1="output1"
INFO2="output2"

info() { echo "
    Here are the test results
    bbb
    ccc
    aaa
    $1
    ";}

echo "First:"
info "$INFO1"

echo "Second:"
info "$INFO2"

或者,使用变量间接,仍然使用函数

#!/bin/bash

INFO1="output1"
INFO2="output2"

info() { echo "
    Here are the test results
    bbb
    ccc
    aaa
    ${!MYINFO}
    ";}

echo "First:"
MYINFO=INFO1
info

echo "Second:"
MYINFO=INFO2
info

答案 2 :(得分:1)

在bash 4.3中,您可以使用 namevars (以前称为ksh功能)在变量之间建立链接,这些变量的行为符合您的意图:

var1="hello"
declare -n var=var1    ## declare -n makes var a "namevar" pointing to var1
var="goodbye"
echo "$var1"

...运行时会发出goodbye

那就是说,因为你要找的是一个模板envsubst是适合这项工作的工具 - 虽然它支持间接扩展本身:

info_template='Here are the test results
${my_info}'

info_good='Successful test!'
info_bad='Failure!'
result=good
result_var=info_$result

my_info="${!result_var}" envsubst <<<"$info_template"

eval不同,envsubst不容易出现安全漏洞。在显示测试输出时,通过将间接扩展移动到模板本身,可以说这比使代码更轻薄更合适。