chamando outras variáveis em um nome de variável (Bash)

7

No momento, tenho os próximos caminhos

langs="EN GE"
dir_EN=/xx
dir_GE=/zz

Como você pode ver, a variável $ langs tem todas as linguagens possíveis em uma única matriz. Gostaria de salvar todos esses caminhos em um array multilíngüe (dir_ML) usando um loop que verifica quais são os idiomas e, em seguida, salve o caminho correspondente. Aqui está o que eu tenho até agora

for i in $(seq 0 1); do #I used seq because I didn't know how to specify the length of the variable $langs
    dir_ML[$i]=dir_${langs[$i]}
done

A saída que estou procurando é

dir_ML[0]=/xx

dir_ML[1]=/zz

Espero que você entenda o que estou tentando fazer! Agradecemos antecipadamente

    
por little_mice 07.04.2018 / 17:52

2 respostas

10

langs não é uma matriz, mas uma string no seu código.

Para criar uma matriz e usá-la:

langs=( EN GE )
dir_EN=/xx
dir_GE=/zz

dir_ml=()
for i in "${langs[@]}"; do
    declare -n p="dir_$i"
    dir_ml+=( "$p" )
done

printf 'dir_ml = "%s"\n' "${dir_ml[@]}"

No loop acima, $i receberá os valores EN e GE por sua vez. Isso também introduz uma variável referência de nome p . Quando o valor de p é acessado, a string que foi atribuída à variável quando foi declarada será interpretada como um nome de variável e o valor da variável é retornado.

A saída dos itens acima será

dir_ml = "/xx"
dir_ml = "/zz"

Para usar referências de nome em bash , você precisará de bash versão 4.3 ou posterior.

Outra possibilidade interessante (mas inferior):

dir_EN=/xx
dir_GE=/zz

# (can't set dir_ml=() here as its name would be picked up by the loop)
unset dir_ml

for i in "${!dir_@}"; do
    dir_ml+=( "${!i}" )
done

printf 'dir_ml = "%s"\n' "${dir_ml[@]}"

Aqui, $i obterá os valores dos nomes das variáveis dir_EN e dir_GE por sua vez. Em seguida, usamos variável indireta com ${!i} para obter o valor dessa variável. Essa variação não precisa da matriz langs , mas assume que nenhuma outra variável é chamada dir_ -something (que pode ser considerada um pouco frágil, pois um usuário pode facilmente injetar variáveis com nomes como estes no ambiente do script).

A saída é a mesma para este código que para o código acima.

    
por 07.04.2018 / 18:18
6

Isso pode ser feito da seguinte forma:

#!/bin/bash
langs=(EN GE)
dir_EN=/xx
dir_GE=/zz

for i in ${!langs[@]}; do
        temp="dir_${langs[i]}"
        dir_ML[i]=${!temp}
done

Primeiro, mudei langs="EN GE" para langs=(EN GE) porque isso precisa ser uma matriz.

Eu também alterei $(seq 0 1) para ${!langs[@]} , que será expandido para o índice (ou nome no caso de uma matriz associativa) de cada item na matriz. Então, neste exemplo 0 1 .

Em seguida, defino uma variável temporária como dir_${langs[i]} ( dir_EN e dir_GE ).

Em seguida, usando a expansão do parâmetro ! , eu expandi a variável com esse nome para definir o elemento dir_ML

    
por 07.04.2018 / 18:14