nomes de variáveis ​​dinâmicas (variáveis) do bash


12

Quero criar dinamicamente uma sequência de seqüências de caracteres manipulando uma matriz de elementos e criar algum procedimento aritmético.

for name in FIRST SECOND THIRD FOURTH FIFTH; do
    $name = $(( $6 + 1 ))
    $name = "${$name}q;d"
    echo "${$name}"; printf "\n"
done

O resultado desejado seria o seguinte para $6iguais 0.

1q;d
2q;d
3q;d
4q;d
5q;d

Mas eu recebo esse erro

reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution

Eu acho que é algo simples. Costumava funcionar quando eu fazia algo como

FIRST=$(( $6 + 1 ))
FIRST="${FIRST}q;d"

1
Você pode explicar um pouco melhor. Realmente não entendo o que você está tentando fazer.
Neurônio

O que `$ name = $ (($ 6 + 1))` deve fazer?
PSKocik 11/08/2015

@PSkocik que eu esperava fazerFIRST=$(( $6 + 1 ))
giannis christofakis

Respostas:


16

Primeiro de tudo, não pode haver espaço ao redor = na declaração de variável em bash.

Para conseguir o que deseja, você pode usar eval .

Por exemplo, um exemplo de script como o seu:

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    eval "$name"="'$(( $i + 1 ))q;d'"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done

Impressões:

1q;d
2q;d
3q;d
4q;d
5q;d

Use com evalcautela, algumas pessoas chamam isso de mal por algum motivo válido.

declare funcionaria também:

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    declare "$name"="$(( $i + 1 ))q;d"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done

também imprime:

1q;d
2q;d
3q;d
4q;d
5q;d

Para que serve o !ponto de exclamação printf '%s\n' "${!name}"?
Giannis christofakis

1
É chamado de expansão indireta da expansão de bashparâmetros
Leia

1
Bash também tem uma alternativa mais agradável para declare/ eval: printf -v varname '%fmt' args. Algumas funções internas de conclusão do bash usam isso para chamada por referência. (passe o nome de uma variável para armazenar).
Peter Cordes

Nota: Usar declareapenas define a variável no escopo local, enquanto a evalabordagem a define globalmente.
usuário

11

Se você desejar fazer referência a uma variável bash enquanto mantém o nome armazenado em outra variável, faça o seguinte:

$ var1=hello
$ var2=var1
$ echo ${!var2}
hello

Você armazena o nome da variável que deseja acessar, digamos, var2 nesse caso. Em seguida, você acessa com ${!<varable name>}onde <variable name>está uma variável que contém o nome da variável que você deseja acessar.


Há uma maneira portátil com, eval var=\$$holdermas evalé perigoso!
gavenkoa

1
index=0;                                                                                                                                                                                                           
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    name=$(($index + 1))
    echo "${name}q;d"
    index=$((index+1))
done

É isso que você está tentando?


1

O que recebo do seu código e da sua saída desejada (corrija-me se estiver errado):
Não há uso dos nomes de variável "PRIMEIRO" / "SEGUNDO" / ..., você só precisa de um loop com um índice .. .

Isso fará o trabalho:

for i in {1..5} ; do echo $i"q;d" ; done


Sim, você está certo, exceto, além disso, quero fazer uma função aritmética com uma variável.
Giannis christofakis

Você pode dar um exemplo dessa função aritmética? Você precisa do nome da variável (como "TERCEIRO") para ela ou apenas do valor do índice?
csny

SUM=$(($6 + $i)); echo $SUM"q;d", Vejo o que estava fazendo de errado.
Giannis christofakis
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.