Aufrufen anderer Variablen in einem Variablennamen (Bash)

7

Im Moment habe ich die nächsten Wege

langs="EN GE"
dir_EN=/xx
dir_GE=/zz

Wie Sie sehen können, hat die Variable $ langs alle möglichen Sprachen in einem einzigen Array. Ich möchte alle diese Pfade in einem mehrsprachigen (dir_ML) Array mit einer Schleife speichern, die die Sprachen überprüft, und dann den entsprechenden Pfad speichern. Folgendes habe ich bisher

for i in $(seq 0 1); do #I used seq because I didn't know how to specify the length of the variable $langs
    dir_ML[$i]=dir_${langs[$i]}
done

Die Ausgabe, die ich suche, ist

dir_ML[0]=/xx

dir_ML[1]=/zz

Ich hoffe du kannst verstehen was ich versuche zu tun! Danke im Voraus

little_mice
quelle

Antworten:

10

langs ist kein Array, sondern eine Zeichenfolge in Ihrem Code.

So machen Sie es zu einem Array und verwenden es:

langs=( EN GE )
dir_EN=/xx
dir_GE=/zz

dir_ml=()
for i in "${langs[@]}"; do
    declare -n p="dir_$i"
    dir_ml+=( "$p" )
done

printf 'dir_ml = "%s"\n' "${dir_ml[@]}"

In der obigen Schleife $iwerden die Werte ENund GEwiederum übernommen. Dies stellt auch einen Namen Referenzvariable p. Wenn auf den Wert von pzugegriffen wird, wird die Zeichenfolge, die der Variablen bei ihrer Deklaration zugewiesen wurde, als Variablenname interpretiert und der Wert dieser Variablen zurückgegeben.

Die Ausgabe der oben genannten wird sein

dir_ml = "/xx"
dir_ml = "/zz"

Um Namensreferenzen in verwenden zu können bash, benötigen Sie bashVersion 4.3 oder höher.


Eine andere (interessante, aber minderwertige) Möglichkeit:

dir_EN=/xx
dir_GE=/zz

# (can't set dir_ml=() here as its name would be picked up by the loop)
unset dir_ml

for i in "${!dir_@}"; do
    dir_ml+=( "${!i}" )
done

printf 'dir_ml = "%s"\n' "${dir_ml[@]}"

Hier $iwerden die Werte der Variablennamen dir_EN und der dir_GEReihe nach übernommen. Wir verwenden dann die Variablenindirektion mit ${!i}, um den Wert dieser Variablen zu erhalten. Diese Variante benötigt das langsArray nicht, sondern setzt voraus, dass keine andere Variable mit dem Namen dir_-something bezeichnet wird (was als etwas fragil angesehen werden kann, da ein Benutzer Variablen mit solchen Namen leicht in die Skriptumgebung einfügen kann).

Die Ausgabe ist für diesen Code dieselbe wie für den obigen Code.

Kusalananda
quelle
6

Dies kann wie folgt erreicht werden:

#!/bin/bash
langs=(EN GE)
dir_EN=/xx
dir_GE=/zz

for i in ${!langs[@]}; do
        temp="dir_${langs[i]}"
        dir_ML[i]=${!temp}
done

Zuerst habe ich geändert langs="EN GE", langs=(EN GE)weil dies ein Array sein muss.

Ich habe auch geändert $(seq 0 1), ${!langs[@]}um den Index (oder den Namen im Fall eines assoziativen Arrays) jedes Elements im Array zu erweitern. Also in diesem Beispiel 0 1.

Dann setze ich eine temporäre Variable auf dir_${langs[i]}( dir_ENund dir_GE).

Dann !erweitere ich mit der Parametererweiterung die Variable mit diesem Namen, um das Element von festzulegendir_ML

jesse_b
quelle
Vielen Dank für Ihre Antwort. Wissen Sie? Ich habe noch eine Frage. Könnten Sie mir erklären, warum Sie $ {! Langs [@]} anstelle von $ {langs [@]} (ohne das Fragezeichen) verwendet haben
?
Außerdem möchte ich Sie fragen, warum es in der zweiten Zeile der Schleife nicht erforderlich ist, "$" vor dem i zu verwenden. Sollte es nicht verwendet werden, da es eine Variable ist?
little_mice
1
@little_mice ${!langs[@]}generiert die Indizes des Arrays 0und 1. Das $ist in arithmetischen Zusammenhängen nicht notwendig.
Kusalananda