Riferimento a variabili di array bash da un altro array


8

Voglio scrivere uno script per fare riferimento a più array da un altro array che contiene i nomi delle variabili di questi array.

Ecco il mio codice finora:

#!/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

Vorrei che l'output eseguisse la scansione di entrambi gli array (dall'esterno per il ciclo) e stampasse le rispettive stringhe nell'interno per il ciclo che chiama echo. Il mio output attuale mi sta solo mostrando:

array1
array2

Sarei grato per qualsiasi suggerimento in merito. Grazie!


C'è qualche motivo per cui non puoi semplicemente fare for b in "${array1[@]}" "${array2[@]}"; do ...; done?
Kusalananda

Vorrei che il numero di array fosse flessibile. Pertanto, se aggiungo un array in un secondo momento, lo aggiungerei semplicemente a array_names e lascerei che il loop si occupasse di esso.
chnppp,

Penso che questo sia un caso di espansione indiretta. Vedi stackoverflow.com/questions/8515411/… - ma, fondamentalmente, passare ${a[@]}a ${!a}fa quello che vuoi (credo).
Parkamark,

1
@parkamark No, questo gli dà solo il primo elemento di ogni array. E ${!a[@]}fornisce una lunghezza dell'array a.
Kusalananda

Sì, passare a ${!a}mi sta solo dando i primi elementi.
chnppp,

Risposte:


7

Bash 4.3 e versioni successive supportano "riferimenti ai nomi" o namerefs (esiste un concetto simile in ksh93, ma l'ambito è fastidiosamente diverso ):

#!/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

La variabile arrè una nameref che si comporta come un alias per la variabile denominata (la variabile con nome $ain questo esempio).

Senza namerefs, nelle precedenti versioni di Bash, una soluzione sarebbe quella di creare un nuovo array che contenga tutti gli elementi degli altri array:

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

... un po 'come l' array_namesarray nella domanda, ma con il contenuto di tutti gli array, e poi ripetiamo "${all[@]}".

È anche possibile usarlo eval, ma il codice risultante sembra incredibilmente terribile.

Vedi la risposta di Glenn Jackman per una variante con indiretta variabile (introdotta nella sua forma attuale con Bash versione 2).



0

Come variante di ciò che è stato detto:

#!/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

Accedere invece agli elementi per indice

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.