Referenzieren von Bash-Array-Variablen aus einem anderen Array


8

Ich möchte ein Skript schreiben, um auf mehrere Arrays aus einem anderen Array zu verweisen, das die Variablennamen dieses Arrays enthält.

Hier ist mein Code bisher:

#!/bin/bash
array1=('array1string1' 'array1string2')
array2=('array2string1' 'array2string2')

array_names=('array1' 'array2')

for a in ${array_names[@]}
do
        for b in ${a[@]}
        do
                echo $b
        done
done

Ich möchte, dass die Ausgabe beide Arrays (von der äußeren for-Schleife) durchsucht und die entsprechenden Zeichenfolgen in der inneren for-Schleife druckt, die Echo aufruft. Meine aktuelle Ausgabe zeigt mir nur:

array1
array2

Ich wäre dankbar für Hinweise dazu. Vielen Dank!


Gibt es einen Grund, warum Sie nicht einfach tun können for b in "${array1[@]}" "${array2[@]}"; do ...; done?
Kusalananda

Ich möchte, dass die Anzahl der Arrays flexibel ist. Wenn ich später ein Array hinzufüge, füge ich es einfach zu array_names hinzu und lasse die Schleife sich darum kümmern.
chnppp

Ich denke, dies ist ein Fall für eine indirekte Expansion. Siehe stackoverflow.com/questions/8515411/… - aber im Grunde macht das Wechseln ${a[@]}zu ${!a}das, was Sie wollen (glaube ich).
Parkamark

1
@parkamark Nein, das gibt ihm nur das erste Element jedes Arrays. Und ${!a[@]}gibt eine Länge des Arrays an a.
Kusalananda

Ja, der Wechsel zu ${!a}gibt mir nur die ersten Elemente.
chnppp

Antworten:


7

Bash 4.3 und höher unterstützt "Namensreferenzen" oder Namensreferenzen (ein ähnliches Konzept gibt es in ksh93, aber der Umfang ist ärgerlich unterschiedlich ):

#!/bin/bash

array1=('array1string1' 'array1string2')
array2=('array2string1' 'array2string2')

array_names=('array1' 'array2')

for a in "${array_names[@]}"; do
    declare -n arr="$a"

    for b in "${arr[@]}"; do
        echo "$b"
    done
done

Die Variable arrist ein nameref, der wie ein Alias ​​für die benannte Variable fungiert (die Variable mit dem Namen $ain diesem Beispiel).

Ohne namerefs besteht eine Lösung in früheren Bash-Versionen darin, ein neues Array zu erstellen, das alle Elemente aus den anderen Arrays enthält:

all=( "${array1[@]}" "${array2[@]}" )

... ein bisschen wie das array_namesArray in der Frage, aber mit dem Inhalt aller Arrays, und dann iterieren "${all[@]}".

Es ist auch möglich zu verwenden eval, aber der resultierende Code sieht erstaunlich schrecklich aus.

Siehe Antwort glenn Jackman für eine Variante mit variabler indirection (eingeführt in seiner jetzigen Form mit Bash Version 2).



0

Als Variation dessen, was gesagt wurde:

#!/bin/bash

array1=('array1 string1' 'array1 string2')
array2=('array2 string1' 'array2 string2')
array_names=('array1' 'array2')

for (( i=0; i<${#array_names[@]}; i++ )); do

    declare -n arr="${array_names[i]}"

    for (( j=0; j<${#arr[@]}; j++ )); do
        echo "${arr[j]}"
    done

done

Zugriff auf die Elemente stattdessen über den Index

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.