#bash #hashmap
#bash #ассоциативный массив #ключ-значение #bash4
Вопрос:
Основываясь на ассоциативном массиве в скрипте Bash, мне нужно выполнить итерацию по нему, чтобы получить ключ и значение.
#!/bin/bash
declare -A array
array[foo]=bar
array[bar]=foo
На самом деле я не понимаю, как получить ключ при использовании цикла for-in.
Комментарии:
1. $ declare -A array=( [foo]=bar [bar]=foo ) # Инициализировать все сразу
2. Для небольшого списка ключевых значений вы могли бы рассмотреть это:
for i in a,b c_s,d ; do KEY=${i%,*}; VAL=${i#*,}; echo $KEY" XX "$VAL; done
3. Аналог Zsh (спойлер: в Zsh все намного проще!): superuser.com/questions/737350 /…
4. @math Мне нравится простота этого, пожалуйста, подумайте о том, чтобы сделать это полноценным ответом
Ответ №1:
Доступ к ключам осуществляется с помощью восклицательного знака: ${!array[@]}
, доступ к значениям осуществляется с помощью ${array[@]}
.
Вы можете выполнять итерацию по парам ключ / значение следующим образом:
for i in "${!array[@]}"
do
echo "key : $i"
echo "value: ${array[$i]}"
done
Обратите внимание на использование кавычек вокруг переменной в for
инструкции (плюс использование @
вместо *
). Это необходимо в случае, если какие-либо ключи содержат пробелы.
Путаница в другом ответе проистекает из того факта, что ваш вопрос включает «foo» и «bar» как для ключей, так и для значений.
Комментарии:
1. Это теперь, если назначить все ключи массиву:
array=(${!hash[@]})
2. @Michael-O: Вам нужно заключить расширение параметра в кавычки, чтобы защитить ключи, которые могут содержать пробелы:
array=("${!hash[@]}")
3. @DennisWilliamson, большое спасибо. У меня этого не было в голове.
4. Как мы можем использовать номер аргумента функции вместо переменной? например
for i in "${!$1[@]}"
?5. @pkaramol: Начиная с Bash 4.3, вы можете использовать ссылки на имена. Пример:
declare -A aa; aa['A']=a1; aa['B']=b2; aa['C']=c3; foo () { declare -n assoc=$1; for key in "${!assoc[@]}"; do echo "Key: $key; Value: ${assoc[$key]}"; done; }; foo aa
. Пожалуйста, смотрите BashFAQ / 006 для получения некоторой важной информации.
Ответ №2:
Вы можете получить доступ к ключам с помощью ${!array[@]}
:
bash-4.0$ echo "${!array[@]}"
foo bar
Затем выполнить итерацию по парам ключ / значение несложно:
for i in "${!array[@]}"
do
echo "key :" $i
echo "value:" ${array[$i]}
done
Комментарии:
1. У меня было «!» — даже не заметил, не было ни одного, извините .. 🙂
2.
echo "${!array[@]}"
не сработало на моей машине. Я использую Mac.
Ответ №3:
Используйте эту функцию более высокого порядка, чтобы предотвратить пирамиду гибели
foreach(){
arr="$(declare -p $1)" ; eval "declare -A f="${arr#*=};
for i in ${!f[@]}; do $2 "$i" "${f[$i]}"; done
}
пример:
$ bar(){ echo "$1 -> $2"; }
$ declare -A foo["flap"]="three four" foo["flop"]="one two"
$ foreach foo bar
flap -> three four
flop -> one two
Комментарии:
1. Я не уверен, как это применимо? Разве pyramid of doom не является чисто эстетической проблемой и действительно применима только в объектно-ориентированных языках?
2. не могли бы вы это объяснить? Функция foreach немного сложна. Я не понимаю.
3. Элегантное и лаконичное решение. Функциональное программирование FTW!
Ответ №4:
Добро пожаловать в input associative array 2.0!
clear
echo "Welcome to input associative array 2.0! (Spaces in keys and values now supported)"
unset array
declare -A array
read -p 'Enter number for array size: ' num
for (( i=0; i < num; i ))
do
echo -n "(pair $(( $i 1 )))"
read -p ' Enter key: ' k
read -p ' Enter value: ' v
echo " "
array[$k]=$v
done
echo " "
echo "The keys are: " ${!array[@]}
echo "The values are: " ${array[@]}
echo " "
echo "Key <-> Value"
echo "-------------"
for i in "${!array[@]}"; do echo $i "<->" ${array[$i]}; done
echo " "
echo "Thanks for using input associative array 2.0!"
Выходной сигнал:
Welcome to input associative array 2.0! (Spaces in keys and values now supported)
Enter number for array size: 4
(pair 1) Enter key: Key Number 1
Enter value: Value#1
(pair 2) Enter key: Key Two
Enter value: Value2
(pair 3) Enter key: Key3
Enter value: Val3
(pair 4) Enter key: Key4
Enter value: Value4
The keys are: Key4 Key3 Key Number 1 Key Two
The values are: Value4 Val3 Value#1 Value2
Key <-> Value
-------------
Key4 <-> Value4
Key3 <-> Val3
Key Number 1 <-> Value#1
Key Two <-> Value2
Thanks for using input associative array 2.0!
Входной ассоциативный массив 1.0
(ключи и значения, содержащие пробелы, не поддерживаются)
clear
echo "Welcome to input associative array! (written by mO extraordinaire!)"
unset array
declare -A array
read -p 'Enter number for array size: ' num
for (( i=0; i < num; i ))
do
read -p 'Enter key and value separated by a space: ' k v
array[$k]=$v
done
echo " "
echo "The keys are: " ${!array[@]}
echo "The values are: " ${array[@]}
echo " "
echo "Key <-> Value"
echo "-------------"
for i in ${!array[@]}; do echo $i "<->" ${array[$i]}; done
echo " "
echo "Thanks for using input associative array!"
Вывод:
Welcome to input associative array! (written by mO extraordinaire!)
Enter number for array size: 10
Enter key and value separated by a space: a1 10
Enter key and value separated by a space: b2 20
Enter key and value separated by a space: c3 30
Enter key and value separated by a space: d4 40
Enter key and value separated by a space: e5 50
Enter key and value separated by a space: f6 60
Enter key and value separated by a space: g7 70
Enter key and value separated by a space: h8 80
Enter key and value separated by a space: i9 90
Enter key and value separated by a space: j10 100
The keys are: h8 a1 j10 g7 f6 e5 d4 c3 i9 b2
The values are: 80 10 100 70 60 50 40 30 90 20
Key <-> Value
-------------
h8 <-> 80
a1 <-> 10
j10 <-> 100
g7 <-> 70
f6 <-> 60
e5 <-> 50
d4 <-> 40
c3 <-> 30
i9 <-> 90
b2 <-> 20
Thanks for using input associative array!
Ответ №5:
declare -a arr
echo "-------------------------------------"
echo "Here another example with arr numeric"
echo "-------------------------------------"
arr=( 10 200 3000 40000 500000 60 700 8000 90000 100000 )
echo -e "n Elements in arr are:n ${arr[0]} n ${arr[1]} n ${arr[2]} n ${arr[3]} n ${arr[4]} n ${arr[5]} n ${arr[6]} n ${arr[7]} n ${arr[8]} n ${arr[9]}"
echo -e " n Total elements in arr are : ${arr[*]} n"
echo -e " n Total lenght of arr is : ${#arr[@]} n"
for (( i=0; i<10; i ))
do echo "The value in position $i for arr is [ ${arr[i]} ]"
done
for (( j=0; j<10; j ))
do echo "The length in element $j is ${#arr[j]}"
done
for z in "${!arr[@]}"
do echo "The key ID is $z"
done
~