取消引用串联变量名称

取消引用串联变量名称

我可以做到这一点,但它需要创建一个变量字符串,然后取消引用它。有什么办法可以将其缩短为更简单的语句吗?

#!/bin/bash

FRUITS="BANANA APPLE ORANGE"

BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"

for fruit in $( echo $FRUITS ); do
    fruit_colour="${fruit}_COLOUR"
    echo $fruit is ${!fruit_colour}
done

我已经尝试了很多类似${!"${fruit}_COLOUR"}or\$${fruit}_COLOUR和许多其他变体的方法,但唯一有效的方法是使用字符串。

答案1

首先,您不需要$(echo $FRUITS)for声明中使用。使用就 $FRUITS足够了。然后,您可以使用 删除循环内的其中一行eval

只是eval告诉 bash 创建第二个评估以下陈述(即比其正常评估多一项)。\$第一次求值后仍保留为,$然后下一次求值将其$视为变量名称的开头,该变量名称解析为“Yellow”等。

这样您就不需要单独的步骤来制作临时字符串(我认为这是您问题的主要目的)。

for fruit in $FRUITS ;do
    eval echo $fruit is \$${fruit}_COLOUR
done

对于替代方法,如所提到的帕特里克在评论(上面)中,您可以使用关联数组,其中元素的索引不需要是整数。您可以使用字符串,例如某种水果的名称。下面是一个使用 bash 关联数组的示例:

# This declares an associative array (It unsets it if it already exists)
declare -A colour
colour['BANANA']="Yellow"
colour["APPLE"]="Green or Red"
colour[MARTIAN ORANGE]="Blue"

for fruit in BANANA APPLE "MARTIAN ORANGE" ;do 
    echo "$fruit" is "${colour[$fruit]}"
done

答案2

您可以使用 bash 内置命令eval来执行此操作:

#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"

for fruit in $( echo $FRUITS );
do
    fruit_colour=${fruit}_COLOUR
    eval echo $fruit is \$${fruit_colour}
done

请注意反斜杠美元符号。基本上,“eval”行导致bash 替换$fruit${fruit_color},然后使用eval在调用 之前进行第二轮替换echo

答案3

您不需要 eval 声明。eval在大多数语言中都暗示你做错了什么。

foo_var=10
bar_var=12

# Build a string with your var name of choice
chosen_prefix='foo'
var_name="${chosen_prefix}_var"

# Use bang to deference it
chossen_value=${!var_name}
echo "Chossen value: ${chossen_value}"

相关内容