วิธีการวนซ้ำอาร์เรย์ที่เชื่อมโยงใน Bash


351

ตามอาเรย์ที่เชื่อมโยงกันในสคริปต์ Bash ฉันจำเป็นต้องวนซ้ำเพื่อรับคีย์และค่า

#!/bin/bash

declare -A array
array[foo]=bar
array[bar]=foo

ที่จริงฉันไม่เข้าใจวิธีการรับกุญแจขณะใช้ for-in loop


14
$ อาร์เรย์ประกาศ -A = ([foo] = บาร์ [บาร์] = foo) # initialise ทั้งหมดในครั้งเดียว
anisbet

3
สำหรับรายการของค่าคีย์เล็ก ๆ คุณอาจพิจารณาสิ่งนี้:for i in a,b c_s,d ; do KEY=${i%,*}; VAL=${i#*,}; echo $KEY" XX "$VAL; done
คณิตศาสตร์

คำตอบ:


582

คีย์จะเข้าถึงได้โดยใช้เครื่องหมายอัศเจรีย์: ${!array[@]}ที่ค่า${array[@]}จะเข้าถึงได้โดยใช้

คุณสามารถวนซ้ำคู่คีย์ / ค่าดังนี้:

for i in "${!array[@]}"
do
  echo "key  : $i"
  echo "value: ${array[$i]}"
done

สังเกตการใช้เครื่องหมายคำพูดล้อมรอบตัวแปรในforคำสั่ง (รวมถึงการใช้@แทน*) นี่เป็นสิ่งจำเป็นในกรณีที่ปุ่มใด ๆ มีช่องว่าง

ความสับสนในคำตอบอื่น ๆ มาจากข้อเท็จจริงที่ว่าคำถามของคุณมี "foo" และ "bar" สำหรับทั้งคีย์และค่า


3
นี่คือตอนนี้ถ้ากำหนดคีย์ทั้งหมดให้กับอาร์เรย์:array=(${!hash[@]})
Michael-O

12
@ Michael-O: คุณต้องอ้างการขยายพารามิเตอร์เพื่อป้องกันกุญแจที่อาจมีช่องว่าง:array=("${!hash[@]}")
หยุดชั่วคราวจนกว่าจะมีประกาศ

@DennisWilliamson ขอบคุณมาก ฉันไม่มีสิ่งนี้ในใจของฉัน
Michael-O

เราจะใช้หมายเลขฟังก์ชันอาร์กิวเมนต์แทนตัวแปรได้อย่างไร เช่นfor i in "${!$1[@]}"?
pkaramol

2
@pkaramol: เริ่มต้นใน Bash 4.3 คุณสามารถใช้ namerefs ตัวอย่าง: 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สำหรับข้อมูลสำคัญบางอย่าง
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

42

คุณสามารถเข้าถึงปุ่มด้วย${!array[@]}:

bash-4.0$ echo "${!array[@]}"
foo bar

จากนั้นการวนคู่คีย์ / ค่าซ้ำนั้นง่าย:

for i in "${!array[@]}"
do
  echo "key :" $i
  echo "value:" ${array[$i]}
done

1
ฉันมี "!" - ไม่ได้สังเกตแม้กระทั่งไม่มีใครขอโทษ .. :)
pex

8

ใช้ฟังก์ชันลำดับที่สูงกว่านี้เพื่อป้องกันปิรามิดแห่งการลงโทษ

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
ฉันไม่แน่ใจว่าวิธีนี้ใช้ได้อย่างไร พีระมิดแห่งความพินาศไม่ใช่ปัญหาด้านความสวยงามอย่างแท้จริงและใช้ได้เฉพาะกับภาษาเชิงวัตถุเท่านั้น
Alexej Magura

1
คุณอธิบายได้ไหม ฟังก์ชั่น foreach นั้นค่อนข้างยุ่งยาก ฉันไม่เข้าใจ
Bálint Szigeti

-1
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
~
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.