Bash
如何在全球範圍內聲明 -A MYASSOCIATIVEARRY?
我有與此 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