bash nomi di variabili dinamiche (variabili)


12

Voglio creare dinamicamente una sequenza di stringhe manipolando una matrice di elementi e creando una procedura aritmetica.

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

Il risultato del desiderio sarebbe il seguente per $6uguali 0.

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

Ma ho questo errore

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

Immagino sia qualcosa di semplice. Funzionava quando facevo qualcosa del genere

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

1
Puoi spiegarlo un po 'meglio. Non capisco davvero cosa stai cercando di fare.
neurone,

Cosa dovrebbe fare `$ name = $ (($ 6 + 1))`?
PSkocik,

@PSkocik Speravo di fareFIRST=$(( $6 + 1 ))
giannis christofakis l'

Risposte:


16

Prima di tutto non può esserci spazio attorno =alla dichiarazione delle variabili in bash.

Per ottenere quello che vuoi puoi usare eval.

Ad esempio uno script di esempio come il tuo:

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

Stampe:

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

Usare con evalcautela, alcune persone lo chiamano male per qualche motivo valido.

declare funzionerebbe anche:

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

stampa anche:

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

A cosa serve il !punto esclamativo printf '%s\n' "${!name}"?
giannis christofakis,

1
Si chiama espansione indiretta dell'espansione dei bashparametri ... leggi tutto
heemayl

1
Bash ha anche una più bella alternativa al declare/ eval: printf -v varname '%fmt' args. Alcune funzioni interne di completamento bash lo usano come riferimento per chiamata. (passa il nome di una variabile in cui archiviare).
Peter Cordes,

Nota: l'utilizzo declareimposta solo la variabile nell'ambito locale, mentre l' evalapproccio la imposta a livello globale.
utente

11

Se vuoi fare riferimento a una variabile bash mentre hai il nome memorizzato in un'altra variabile puoi farlo come segue:

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

Memorizzi il nome della variabile a cui vuoi accedere, diciamo, var2 in questo caso. Quindi si accede con ${!<varable name>}dove si <variable name>trova una variabile che contiene il nome della variabile a cui si desidera accedere.


C'è un modo portatile con eval var=\$$holderma evalè pericoloso!
gavenkoa,

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

È quello che stai provando?


1

Cosa ottengo dal tuo codice e dall'output desiderato (correggimi se sbaglio):
non c'è alcun uso dei nomi delle variabili "PRIMO" / "SECONDO" / ..., hai solo bisogno di un ciclo con un indice. .

Questo farà il lavoro:

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


Sì, hai ragione, tranne che voglio fare una funzione aritmetica con una variabile.
giannis christofakis,

Puoi fare un esempio di questa funzione aritmetica? Ti serve il nome della variabile (come "THIRD") o solo il valore dell'indice?
csny,

SUM=$(($6 + $i)); echo $SUM"q;d", Vedo cosa stavo facendo di sbagliato.
giannis christofakis,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.