Bash

同時在 2 個數組的相同索引中回顯值

  • April 11, 2022

我有 2 個數組要同時在 bash 腳本中處理。第一個數組包含某種標籤。第二個數組包含值,如下所示

LABELS=(label1 label2 label3 labe4 )
VALUES=(91 18 7 4)

需要的是:一個循環,它將回顯 LABELS 數組 & 中的索引項,並在 VALUES 數組中該項的相應值前面,如下所示

label1 91
label2 18
label3 7
label4 4

我猜嵌套循環不起作用,我在下面嘗試過,但它不會按語法工作

for label in {LABELS[@]} && value in {VALUES[@]}
do
   echo ${label} ${value}
done

只需使用數字索引並通過索引引用數組元素:

labels=(label1 label2 label3 label4)
values=(91 18 7 4)


for((i=0; i<"${#labels[@]}"; i++ )); do
 printf '%s: %s\n' "${labels[i]}" "${values[i]}"
done

或者,如果您使用的是相對較新的(>= 版本 4)bash 或其他支持關聯數組的 shell,只需使用單個數組即可:

declare -A values=( ["label1"]=91 ["label2"]=18 \
                   ["label3"]=7 ["label4"]=4 )

for label in "${!values[@]}"; do
 printf '%s: %s\n' "$label" "${values[$label]}"
done

我將變數名稱更改為小寫,因為在 shell 腳本中對局部變數使用大寫字母是不好的做法,因為全域環境變數按約定大寫,因此在腳本中使用大寫字母可能會導致變數名稱衝突。

由於您的兩個數組具有完全相同的索引(0、1、2 和 3),因此您可以使用${!array[@]}迭代其中一個數組的索引(AKA 鍵)並使用該迭代器訪問兩個數組中的值。

這適用於“索引數組”(即整數索引)和“關聯數組”(字元串索引)。

例如

LABELS=(label1 label2 label3 labe4 )
VALUES=(91 18 7 4)

for i in "${!LABELS[@]}"; do
 echo "${LABELS[i]}" "${VALUES[i]}"
done

輸出:

label1 91
label2 18
label3 7
labe4 4

順便說一句,您還可以使用這樣的循環來填充關聯數組,這在您不能同時讀取鍵和值的情況下很有用,就像您的兩個手動定義的數組一樣:

LABELS=(label1 label2 label3 labe4)
VALUES=(91 18 7 4)

declare -A LV # declare LV to be an associative array

for i in "${!LABELS[@]}"; do
 LV["${LABELS[$i]}"]="${VALUES[$i]}";
done

declare -p LV

輸出:

declare -A LV=([labe4]="4" [label3]="7" [label2]="18" [label1]="91" )

從現在開始,您的腳本可以使用關聯數組$LV直接訪問鍵中的值,例如

$ echo "${LV[label1]}"
91

您還可以使用 C 風格的 for 循環,如 @terdon 和 @NickMatteo 的答案(從 0 循環到數組的長度),但這僅適用於數組索引是數字且連續且數組中沒有間隙(未定義索引)的情況.

在許多/大多數情況下,這很好,因為數組通常用連續的索引號定義的,但在其他情況下,它不會按預期工作 - 例如,如果為 1、3、5、7、11、13、17$array定義了索引然後${#array[@]}將返回 7 並且這樣的循環將從 0..6 (如果您使用<=而不是<作為測試條件,則為 0..7 )而不是數組中的實際索引列表進行迭代。

例如:

$ for i in 1 3 5 7 11 13 17 ; do let array[$i]=$i*$i ; done

$ declare -p array
declare -a array=([1]="1" [3]="9" [5]="25" [7]="49" [11]="121" [13]="169" [17]="289")

$ echo "${#array[@]}"
7

$ for ((i=0; i<"${#array[@]}"; i++)); do echo $i: "${array[$i]}" ; done
0: 
1: 1
2: 
3: 9
4: 
5: 25
6: 

$ echo "${!array[@]}"
1 3 5 7 11 13 17

$ for i in "${!array[@]}"; do echo $i: "${array[$i]}"; done
1: 1
3: 9
5: 25
7: 49
11: 121
13: 169
17: 289

引用自:https://unix.stackexchange.com/questions/698502