Referenciando variáveis ​​do array bash de outro array


8

Eu quero escrever um script para referenciar várias matrizes de outra matriz que contém os nomes de variáveis ​​dessa matriz.

Aqui está o meu código até agora:

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

Gostaria que a saída digitalizasse as duas matrizes (a partir do loop for externo) e imprimisse as respectivas strings no loop for interno que chama eco. Minha saída atual está apenas me mostrando:

array1
array2

Eu ficaria grato por qualquer indicação sobre isso. Obrigado!


Existe alguma razão pela qual você não pode simplesmente fazer for b in "${array1[@]}" "${array2[@]}"; do ...; done?
Kusalananda

Eu gostaria que o número de matrizes fosse flexível. Portanto, se eu adicionar uma matriz posteriormente, eu a adicionaria a array_names e deixaria o loop cuidar disso.
chnppp

Eu acho que esse é um caso de expansão indireta. Veja stackoverflow.com/questions/8515411/… - mas, basicamente, mudar ${a[@]}para ${!a}o que você deseja (eu acho).
parkamark

1
@parkamark Não, isso apenas fornece a ele o primeiro elemento de cada array. E ${!a[@]}fornece um comprimento da matriz a.
Kusalananda

Sim, mudar para ${!a}é apenas me dar os primeiros elementos.
chnppp

Respostas:


7

O Bash 4.3 e versões posteriores suportam "referências de nomes" ou namerefs (existe um conceito semelhante ksh93, mas o escopo é irritantemente diferente ):

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

A variável arré um nameref que age como um alias para a variável nomeada (a variável com nome $aneste exemplo).

Sem namerefs, nas versões anteriores do Bash, uma solução seria criar uma nova matriz que contenha todos os elementos das outras matrizes:

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

... um pouco como a array_namesmatriz da pergunta, mas com o conteúdo de todas as matrizes e, em seguida, iterar "${all[@]}".

Também é possível usar eval, mas o código resultante parece surpreendentemente terrível.

Veja a resposta de glenn jackman para uma variação com indireção variável (introduzida em sua forma atual com a versão 2 do Bash).



0

Como uma variação do que foi dito:

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

Acessando os elementos por índice

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.