Cos'è l'espansione indiretta? Cosa significa $ {! Var *}?


87

Sto leggendo " Bash Guide for Beginners ". Dice:

Se il primo carattere di PARAMETERè un punto esclamativo, Bash usa il valore della variabile formata dal resto di PARAMETERcome nome della variabile; questa variabile viene quindi espansa e quel valore viene utilizzato nel resto della sostituzione, piuttosto che il valore PARAMETERstesso. Questo è noto come espansione indiretta.

L'esempio fornito è:

franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH

Non capisco bene qui:

il valore della variabile formata dal resto di PARAMETER

Come PARAMETERè giusto !N*, allora

il resto di PARAMETER

è solo N*. Come potrebbe questo formare una variabile? Bash ha cercato lì tutti i possibili comandi?

Risposte:


112

Se leggi la bashpagina man, sostanzialmente conferma ciò che hai affermato:

Se il primo carattere di parametro è un punto esclamativo ( !), viene introdotto un livello di riferimento indiretto variabile. Bash utilizza il valore della variabile formato dal resto del parametro come nome della variabile; questa variabile viene quindi espansa e quel valore viene utilizzato nel resto della sostituzione, piuttosto che il valore del parametro stesso. Questo è noto come espansione indiretta.

Tuttavia, continuando a leggere da lì:

Le eccezioni sono le espansioni di ${!prefix*}e ${!name[@]}descritte di seguito.

${!prefix*}Nomi che corrispondono al prefisso. Si espande ai nomi delle variabili i cui nomi iniziano con prefisso, separati dal primo carattere della IFSvariabile speciale.

In altre parole, il tuo esempio particolare ${!N*}è un'eccezione alla regola che hai citato. Essa ha , tuttavia, il lavoro come pubblicizzato nei casi previsti, come ad esempio:

$ export xyzzy=plugh ; export plugh=cave

$ echo ${xyzzy}  # normal, xyzzy to plugh
plugh

$ echo ${!xyzzy} # indirection, xyzzy to plugh to cave
cave

1
Grazie per la risposta. Più leggo "Bash guide for Beginners" e più mi chiedo se l'autore capisce quello che scrive.
LRDPRDX

24

Sembra che ci sia un'eccezione quando il dato "riferimento indiretto" termina in a *, come avviene qui. In questo caso, fornisce tutti i nomi delle variabili che iniziano con la parte specificata ( Nqui). Bash può farlo perché tiene traccia delle variabili e sa quali esistono.

Il vero riferimento indiretto è questo:
supponiamo di avere una variabile $VARIABLEimpostata su 42e un'altra variabile $NAMEimpostata su VARIABLE. ${!NAME}mi darà 42. Usa il valore di una variabile per dirti il ​​nome di un'altra:

$ NAME="VARIABLE"
$ VARIABLE=42
$ echo ${!NAME}
42

6
Wow, chi sapeva che era così facile ottenere la risposta al significato della vita, dell'universo e di tutto!
KomodoDave

3

Sì, cerca tutte le possibili espansioni di variabili dopo!. Se avessi fatto:

echo ${!NP*}

otterresti solo NPX_PLUGIN_PATH.

Considera il seguente esempio:

:~> export myVar="hi"
:~> echo ${!my*}
    myVar
:~> export ${!my*}="bye"
:~> echo $myVar
    bye

anche altre variabili che corrispondono al mio * sarebbero impostate su "bye"?
Anthony

1
@Anthony l'ho provato, e se si ${!my*}espande in myA, myB, myA viene esportato con il suo valore corrente e myB è impostato su "bye" ed esportato. Non molto utile.
GKFX

3

Hai riscontrato un'eccezione nell'elaborazione indiretta, dove se l'ultimo carattere è *, verranno restituite tutte le variabili che hanno il prefisso fornito prima.


Quindi, a parte il *caso, è lo stesso di ${${VAR}}?
chronospoon

1
@chronospoon``, ${${VAR}}più brevemente scrivibile come ${$VAR}, non è legale, poiché $VARrestituisce una stringa, che non può seguire il $segno; per utilizzare una stringa come nome di una variabile è necessario introdurre un livello di riferimento indiretto (come citato nella domanda originale stessa), ovvero è possibile utilizzare ${!VAR}, che fa esattamente ciò che ci si aspetterebbe (erroneamente ma comprensibilmente) ${$VAR}.
Enlico

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.