Bash

如何在全球範圍內聲明 -A MYASSOCIATIVEARRY?

  • November 27, 2019

我有與此 SO 文章中描述的完全相同的問題(“帶有冒號的 bash 關聯數組鍵字元串給出錯誤”):https ://stackoverflow.com/q/40406187/10639803

解決方案是使用declare -A,但一旦我這樣做,我的關聯數組就不再是全域的。

declare -A 沒有辦法讓它全球化?

declare -gA更新:我按照此處所述進行了嘗試: https ://stackoverflow.com/a/21151984/10639803但由於某種原因它對我不起作用:一旦退出填充我的關聯數組(雜湊圖)的循環,數組變得不穩定。

這是實際的 bash 程式碼(循環內的 echo 命令用於驗證是否確實提取並分配了值):

declare -gA HOSTS_START_MAP
find "$TEMP" -type f -name "debug.log*" -exec grep -F "STARTING HOST " {} \; |
while IFS= read -r HOST_START_LINE; do
   if [[ $HOST_START_LINE =~ (.*)(DEBUG)(.*)(STARTING HOST)([ 0-9]*)(.*)(CALCULATION) ]]
   then
       HOST_START_TIME=$(echo "${BASH_REMATCH[1]}" | xargs)
       HOST_NAME=$(echo "${BASH_REMATCH[6]}" | xargs)
       # echo ">$HOST_NAME< ... >$HOST_START_TIME<"
       HOSTS_START_MAP[$HOST_NAME]=$HOST_START_TIME
       # echo $HOST_NAME --- ${HOSTS_START_MAP[$HOST_NAME]}
   fi
done

echo ${#HOSTS_START_MAP[@]}
for MYKEY in "${!HOSTS_START_MAP[@]}"; do echo $MYKEY --- ${HOSTS_START_MAP[@]}; done

您看到的問題與變數的聲明無關。這是因為您在子 shell 中設置變數並期望其值在父 shell 中可用。

您可以在此處看到此效果,使用與您的程式碼相同的結構,但使用更簡單的範例:

a=""
echo find | while read item; do a="$item"; done
echo "a=$a"

幸運的是,使用時bash有一個快速的解決方案,可以通過以不同的形式重寫程式碼:

a=""
while read item; do a="$item"; done < <( echo find )
echo "a=$a"

在實際程式碼中,用於while IFS= read -r item確保item接收未處理的輸入。我已經省略了我希望在範例中清晰的保護。


在對此答案的評論中,您要求修改程式碼版本。我無法測試它,這就是為什麼我一開始猶豫把它放在這裡,但它應該看起來像這樣:

#!/bin/bash
#
declare -gA HOSTS_START_MAP
while IFS= read -r HOST_START_LINE; do
   if [[ $HOST_START_LINE =~ (.*)(DEBUG)(.*)(STARTING HOST)([ 0-9]*)(.*)(CALCULATION) ]]
   then
       HOST_START_TIME=$(echo "${BASH_REMATCH[1]}" | xargs)
       HOST_NAME=$(echo "${BASH_REMATCH[6]}" | xargs)
       # echo ">$HOST_NAME< ... >$HOST_START_TIME<"
       HOSTS_START_MAP[$HOST_NAME]=$HOST_START_TIME
       # echo $HOST_NAME --- ${HOSTS_START_MAP[$HOST_NAME]}
   fi
done < <( find "$TEMP" -type f -name "debug.log*" -exec grep -F "STARTING HOST " {} \; )

echo ${#HOSTS_START_MAP[@]}
for MYKEY in "${!HOSTS_START_MAP[@]}"; do echo $MYKEY --- ${HOSTS_START_MAP[@]}; done

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