Nome da variável concatenada de desreferência

10

Eu posso fazer isso, mas é necessário criar uma string da variável e então desreferencia-la. Existe alguma maneira de encurtá-lo para uma declaração mais simples?

#!/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

Eu tentei muitas coisas como ${!"${fruit}_COLOUR"} ou \$${fruit}_COLOUR e muitas outras variantes, mas a única maneira que funcionou é usando uma string.

    
por Mat 20.02.2012 / 22:53

3 respostas

9

Primeiro, você não precisa usar $(echo $FRUITS) na instrução for . Usando apenas $FRUITS é suficiente. Então você pode acabar com uma das linhas dentro do loop, usando eval .

O eval diz ao bash para fazer uma segunda avaliação da seguinte declaração (ou seja, mais uma do que a avaliação normal). O \$ sobrevive à primeira avaliação como $ e a próxima avaliação trata esse $ como o início de um nome de variável, que é resolvido como "Amarelo", etc.

Desta forma, você não precisa ter uma etapa separada, que faça uma sequência provisória (que é o que acredito ser a intenção principal da sua pergunta).

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

Para um método alternativo, como mencionado por Patrick em um comentário (acima), você pode usar uma matriz associativa , na qual o índice de um elemento não precisa seja um inteiro. Você pode usar uma string, como o nome de um tipo de fruta. Aqui está um exemplo, usando o array associativo do 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
    
por 21.02.2012 / 01:48
6

Você pode usar o bash-builtin eval para fazer isso:

#!/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

Observe o sinal de dólar invertido. Basicamente, a linha "eval" causa bash  para substituir $fruit e ${fruit_color} e, em seguida, usar eval para executar uma segunda rodada de substituição antes de chamar echo .

    
por 20.02.2012 / 23:32
0

Você não precisa de uma declaração eval. eval é uma dica na maioria das linguagens de que você está fazendo algo errado.

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}"
    
por 13.08.2018 / 14:02