È possibile stampare il contenuto di una variabile con script di shell? (riferimento indiretto)


13

Supponiamo di aver dichiarato le seguenti variabili:

$ var='$test'
$ test="my string"

Se stampo il loro contenuto vedo quanto segue:

$ echo $var
$test

$ echo $test
my string

Vorrei trovare un modo per stampare il contenuto del contenuto $var(che è il contenuto di $test). Quindi ho provato a fare quanto segue:

$ echo $(echo $var)
$test

Ma qui il risultato è $teste non "my string"... È possibile stampare il contenuto delle variabili usando bash?


Potresti modificare il tuo post per dire quale shell stai usando o quali requisiti di portabilità hai?
Michael Homer,

@MichaelHomer Certo, ma come posso controllare esattamente queste informazioni?
Rafael Muynarsk,

È più qualcosa che scegli che qualcosa da controllare. Ad esempio, stai eseguendo i tuoi script con ash, o bash, oppure csh, oppure dash, ... o zshoppure POSIX sho devi lavorare su sistemi diversi?
Michael Homer,

@MichaelHomer Ah, vedo ... sto usando bash. Cambierò solo l'ultima domanda e inserirò un nuovo tag.
Rafael Muynarsk,

Risposte:



10

Nel caso in cui il nome della variabile contenuto varsia preceduto da un prefisso, $è possibile utilizzare eval:

$ var='$test'
$ test="my string"
$ eval echo $var
my string

Che succede qui:

  • bash si espande $varal valore $test, producendo un eval echo $testcomando;
  • evalvaluta l' echo $testespressione e produce il risultato desiderato.

Si noti che l'utilizzo evalin generale può essere pericoloso (a seconda di ciò che viene memorizzato var), quindi preferisco evitarlo. La funzionalità di espansione indiretta è migliore per il tuo caso (ma devi eliminare l' $accesso $test).


Certo, è un errore di battitura. Il post originale ha virgolette singole. Fisso.
Danila Kiver,

4
Consiglio sempre riferimenti a virgolette doppie tra virgolette (per evitare problemi dovuti alla divisione inattesa delle parole e all'espansione dei caratteri jolly). Con eval, avete bisogno di due strati di virgolette, allineare questo: eval echo "\"$var\"". Intendiamoci, questo non fa nulla per gli altri pericoli dell'uso evalche hai citato.
Gordon Davisson,

9

Simile alla risposta di Jesse_b , ma usando una variabile di riferimento al nome invece della variabile indiretta (richiede bash4.3+):

$ declare -n var=test
$ test="my string"
$ echo "$var"
my string

La variabile di riferimento vardel nome contiene il nome della variabile a cui fa riferimento. Quando la variabile viene definita come $var, viene restituito il valore dell'altra variabile.

bash risolve ricorsivamente i riferimenti ai nomi:

$ declare -n var1=var2
$ declare -n var2=test
$ test="hello world"
$ echo "$var1"
hello world

Per completezza, l'utilizzo di un array associativo (in bash4.0+) è anche un modo di risolverlo, a seconda dei requisiti:

$ declare -A strings
$ strings[test]="my string"
$ var=test
$ echo "${strings[$var]}"
my string

Ciò fornisce un modo più flessibile di accedere a più di un valore con una chiave o un nome che può essere determinato in modo dinamico. Questo può essere preferibile se si desidera raccogliere tutti i valori di una particolare categoria in un singolo array, ma essere comunque in grado di accedervi mediante una chiave (ad esempio nomi accessibili tramite ID, o percorsi accessibili per scopo ecc.) In quanto non inquina lo spazio dei nomi variabile dello script.


3

Con zsh:

$ var='$test'
$ test='*'
$ printf '%s\n' ${(e)var}
*

Con qualsiasi guscio tipo Bourne

$ eval 'printf "%s\n" "'"$var"'"'
*

Ricorda che in quelle shell le espansioni variabili devono essere quotate per evitare split + glob ( zshessendo un'eccezione) e echonon possono essere usate per dati arbitrari.

Dato che con entrambi (e)e evalc'è la valutazione del codice della shell, è importante che il contenuto $varrimanga sotto il tuo controllo, altrimenti potrebbe trattarsi di una vulnerabilità arbitraria all'iniezione di comandi (lo stesso con gli ${!var}approcci).

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.