Was ist indirekte Expansion? Was bedeutet $ {! Var *}?

85

Ich lese " Bash Guide für Anfänger ". Es sagt:

Wenn das erste Zeichen von PARAMETERein Ausrufezeichen ist, verwendet Bash den Wert der Variablen, die aus dem Rest von gebildet wird, PARAMETERals Namen der Variablen. Diese Variable wird dann erweitert und dieser Wert wird im Rest der Substitution anstelle des Werts von sich PARAMETERselbst verwendet. Dies wird als indirekte Expansion bezeichnet.

Das gegebene Beispiel ist:

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

Ich verstehe hier nicht ganz:

der Wert der Variablen, die aus dem Rest von gebildet wird PARAMETER

Wie das PARAMETERgerade ist !N*, dann

der Rest von PARAMETER

ist einfach N*. Wie könnte dies eine Variable bilden? Hat Bash dort alle möglichen Befehle durchsucht?

Athos
quelle

Antworten:

106

Wenn Sie die bashManpage lesen , bestätigt dies im Wesentlichen, was Sie angegeben haben:

Wenn das erste Zeichen des Parameters ein Ausrufezeichen ( !) ist, wird eine Ebene der variablen Indirektion eingeführt. Bash verwendet den Wert der aus dem Rest des Parameters gebildeten Variablen als Namen der Variablen. Diese Variable wird dann erweitert und dieser Wert wird im Rest der Substitution anstelle des Werts des Parameters selbst verwendet. Dies wird als indirekte Expansion bezeichnet.

Lesen Sie jedoch weiter:

Ausnahmen bilden die nachfolgend beschriebenen ${!prefix*}und ${!name[@]}beschriebenen Erweiterungen .

${!prefix*}Namen, die dem Präfix entsprechen. Erweitert sich zu den Namen von Variablen, deren Namen mit dem Präfix beginnen, getrennt durch das erste Zeichen der IFSSondervariablen.

Mit anderen Worten, Ihr spezielles Beispiel ${!N*}ist eine Ausnahme von der von Ihnen angegebenen Regel. Es funktioniert jedoch wie angekündigt in den erwarteten Fällen, wie z.

$ export xyzzy=plugh ; export plugh=cave

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

$ echo ${!xyzzy} # indirection, xyzzy to plugh to cave
cave
paxdiablo
quelle
Danke für die Antwort. Je mehr ich "Bash Guide for Beginners" lese, desto mehr frage ich mich, ob die Autorin versteht, was sie schreibt.
LRDPRDX
23

Es scheint eine Ausnahme zu geben, wenn die angegebene "Indirektion" *wie hier mit a endet . In diesem Fall werden alle Variablennamen angegeben, die mit dem von Ihnen angegebenen Teil beginnen ( Nhier). Bash kann das, weil es Variablen verfolgt und weiß, welche existieren.

Wahre Indirektion ist folgende:
Angenommen, ich habe eine Variable $VARIABLEauf 42und ich habe eine andere Variable auf $NAMEgesetzt VARIABLE. ${!NAME}werde mir geben 42. Sie verwenden den Wert einer Variablen, um den Namen einer anderen Variablen anzugeben:

$ NAME="VARIABLE"
$ VARIABLE=42
$ echo ${!NAME}
42
Kevin
quelle
4
Wow, wer wusste, dass es so einfach ist, die Antwort auf den Sinn des Lebens, des Universums und alles zu bekommen!
KomodoDave
3

Ja, es wird nach allen möglichen Erweiterungen von Variablen nach dem! Gesucht. Wenn Sie getan hätten:

echo ${!NP*}

du würdest nur bekommen NPX_PLUGIN_PATH.

Betrachten Sie das folgende Beispiel:

:~> export myVar="hi"
:~> echo ${!my*}
    myVar
:~> export ${!my*}="bye"
:~> echo $myVar
    bye
tpg2114
quelle
Würden andere Variablen, die mit meinem * übereinstimmen, ebenfalls auf "bye" gesetzt?
Anthony
1
@Anthony Ich habe es versucht, und wenn es ${!my*}zu myA, myB erweitert wird, wird myA mit seinem aktuellen Wert exportiert und myB wird auf "bye" gesetzt und exportiert. Nicht sehr nützlich.
GKFX
3

Bei der Indirektionsverarbeitung ist eine Ausnahme aufgetreten. Wenn das letzte Zeichen lautet *, werden alle Variablen mit dem zuvor angegebenen Präfix zurückgegeben.

Ignacio Vazquez-Abrams
quelle
Also, abgesehen von dem *Fall, ist das dasselbe wie ${${VAR}}?
Chronospoon
1
@chronospoon, ${${VAR}}kurz beschreibbar als ${$VAR}, ist nicht legal, da $VAReine Zeichenfolge zurückgegeben wird, die dem $Vorzeichen nicht folgen kann . Um eine Zeichenfolge als Variablennamen zu verwenden, müssen Sie eine Indirektionsebene einführen (wie in der ursprünglichen Frage selbst angegeben), dh Sie können verwenden ${!VAR}, die genau das tut, was Sie erwarten würden (fälschlicherweise, aber verständlich) ${$VAR}.
Enrico Maria De Angelis