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.