Follow-up zum Hintergrundteil dieser Frage .
In bash
kann ich verwende ${!FOO}
für doppelte Substitution, in zsh
${(P)FOO}
. In beiden Fällen eval \$$FOO
funktioniert die alte Schule (Hack-y) .
Das Klügste und Logischste für mich wäre also ${${FOO}}, ${${${FOO}}}…
eine doppelte / dreifache / n-Substitution. Warum funktioniert das nicht wie erwartet?
Zweitens: Was macht der \
in der eval
Aussage? Ich denke, es ist eine Flucht, die so etwas wie eval \$$$FOO
unmöglich macht. Wie macht man eine Triple / N-Substitution mit der, die in jeder Shell funktioniert?
quelle
l3=l2; eval eval eval echo \\\$\\$\$$l3
→53294
also nicht genau modular.eval $(eval echo \$$l2)
? Ich hasse Bash, es macht absolut keinen Sinn.quelle
Angenommen, der Wert von
FOO
ist ein gültiger Variablenname (sayBAR
),eval \$$FOO
der Wert von wirdBAR
in separate Wörter aufgeteilt, jedes Wort wird als Platzhaltermuster behandelt und das erste Wort des Ergebnisses wird als Befehl ausgeführt, wobei die anderen Wörter als Argumente übergeben werden. Der umgekehrte Schrägstrich vor dem Dollar führt zu einer wörtlichen Behandlung. Das Argument, das an deneval
Builtin übergeben wird, ist die Zeichenfolge mit vier Zeichen$BAR
.${${FOO}}
ist ein Syntaxfehler. Es wird keine "doppelte Ersetzung" durchgeführt, da es in keiner der gängigen Shells eine solche Funktion gibt (ohnehin nicht mit dieser Syntax). In zsh${${FOO}}
ist gültig und ist eine doppelte Substitution, aber es verhält sich anders als gewünscht: Es werden zwei aufeinanderfolgende Transformationen des Werts von ausgeführtFOO
, wobei beide die Identitätsumwandlung sind, sodass es sich nur um eine ausgefallene Schreibweise handelt${FOO}
.Wenn Sie den Wert einer Variablen als eine Variable behandeln möchten, achten Sie darauf, die Dinge richtig in Anführungszeichen zu setzen. Es ist viel einfacher, wenn Sie das Ergebnis auf eine Variable setzen:
quelle
{ba,z}sh
LösungHier ist eine Funktion, die in beiden Fällen funktioniert
{ba,z}sh
. Ich glaube, es ist auch POSIX-konform.Ohne verrückt nach Zitieren zu werden, können Sie es für viele Indirektionsebenen verwenden:
Oder wenn Sie mehr (!?!) Indirektionsebenen haben, können Sie eine Schleife verwenden.
Es warnt, wenn gegeben:
quelle
Genau wie
${$foo}
funktioniert nicht anstelle von${(P)foo}
inzsh
, auch nicht${${$foo}}
. Sie müssen nur die einzelnen Indirektionsebenen angeben:Funktioniert natürlich
${!${!foo}}
nichtbash
, dabash
keine verschachtelten Ersetzungen zulässig sind.quelle
zsh
es viel öfter installiert wird, als Sie vielleicht annehmen. Es kann sein, dass es nichtsh
wiebash
oft verlinkt ist (aber nicht immer), aber es kann immer noch für Shell-Skripte verfügbar sein. Stellen Sie es sich wie Perl oder Python vor.Warum müssten Sie das tun?
Sie können dies immer in mehreren Schritten tun:
Oder benutze eine Funktion wie:
Dann:
FWIW, in
zsh
:quelle
POSIX-Lösung
Ohne verrückt nach Zitaten zu werden, können Sie diese Funktion für viele Indirektionsebenen verwenden:
Oder wenn Sie mehr (!?!) Indirektionsebenen haben, können Sie eine Schleife verwenden.
Es warnt, wenn gegeben:
quelle