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.