2015-04-22 18 views
6

Czy ktoś wie o eleganckim sposobie łączenia dwóch tablic asocjacyjnych w bash, podobnie jak w zwykłej tablicy? Oto, co mówię:Jak łączyć tablice asocjacyjne w bashu?

W bashu można połączyć dwa zwykłe tablice następująco:

declare -ar array1=(5 10 15) 
declare -ar array2=(20 25 30) 
declare -ar array_both=(${array1[@]} ${array2[@]}) 

for item in ${array_both[@]}; do 
    echo "Item: ${item}" 
done 

chcę zrobić to samo z dwoma asocjacyjnych, ale następujący kod nie działa:

declare -Ar array1=([5]=true [10]=true [15]=true) 
declare -Ar array2=([20]=true [25]=true [30]=true) 
declare -Ar array_both=(${array1[@]} ${array2[@]}) 

for key in ${!array_both[@]}; do 
    echo "array_both[${key}]=${array_both[${key}]}" 
done 

To daje następujący błąd:

./associative_arrays.sh: line 3: array_both: true: must use subscript when assigning associative array

Poniżej znajduje się praca-ar ound wymyśliłem:

declare -Ar array1=([5]=true [10]=true [15]=true) 
declare -Ar array2=([20]=true [25]=true [30]=true) 
declare -A array_both=() 

for key in ${!array1[@]}; do 
    array_both+=([${key}]=${array1[${key}]}) 
done 

for key in ${!array2[@]}; do 
    array_both+=([${key}]=${array2[${key}]}) 
done 

declare -r array_both 

for key in ${!array_both[@]}; do 
    echo "array_both[${key}]=${array_both[${key}]}" 
done 

Ale mam nadzieję, że ja rzeczywiście brakuje trochę gramatyki, która pozwoli na przypisanie jednego-liner, jak pokazano na przykład zakaz pracy.

Dzięki!

+1

Jeden wkładka musiałyby być w stanie rozszerzać się w tablicy '[] = kluczowych elementów value' dla każdego przycisku. Nie znam żadnego takiego rozszerzenia. Najbliższe, o czym mogę pomyśleć, to to, co daje ci 'declare-p' (które musisz masować, aby użyć). –

+0

Cóż, spędziłem dużo czasu bawiąc się tablicami, rozszerzaniem parametrów i zmiennymi bash. Myślę, że można bezpiecznie powiedzieć, że "obejście" w twoim pytaniu jest najczystszym sposobem na skopiowanie tablicy asocjacyjnej. Mimo to mógłbym uczynić twój skrypt jednym "linerem" z garścią średników, gdybyś naprawdę chciał ...;) – vastlysuperiorman

Odpowiedz

2

Nie mam również jednej linijki, ale tutaj jest inne "obejście", które ktoś może lubić, używając konwersji ciągów. To 4 linie, więc mam tylko 3 średniki od odpowiedzi, której szukałeś!

declare -Ar array1=([5]=true [10]=true [15]=true) 
declare -Ar array2=([20]=true [25]=true [30]=true) 

# convert associative arrays to string 
a1="$(declare -p array1)" 
a2="$(declare -p array2)" 

#combine the two strings trimming where necessary 
array_both_string="${a1:0:${#a1}-3} ${a2:21}" 

# create new associative array from string 
eval "declare -A array_both="${array_both_string#*=} 

# show array definition 
for key in ${!array_both[@]}; do 
    echo "array_both[${key}]=${array_both[${key}]}" 
done 
+0

Tak, to z pewnością alternatywne podejście do pracy, które buduje komentarz Etana. Nie jest to jednak intuicyjne spojrzenie na kod, więc prawdopodobnie pozostanę przy moim obejściu. –

0
#!/bin/bash 

function merge_hashes() { 
    local -n DEST_VAR=$1 
    shift 

    local -n SRC_VAR 
    local KEY 

    for SRC_VAR in [email protected]; do 
     for KEY in "${!SRC_VAR[@]}"; do 
      DEST_VAR[$KEY]="${SRC_VAR[$KEY]}" 
     done 
    done 
} 

declare -Ar array1=([5]=true [10]=true [15]=true) 
declare -Ar array2=([20]=true [25]=true [30]=true) 
declare -A array_both=() 

# And here comes the one-liner: 
merge_hashes array_both array1 array2 

declare -p array_both 
+0

Czy możesz podać jakieś wyjaśnienie również? – d4Rk