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

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

我有與此 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

答案1

您看到的問題與變數的聲明無關。這是因為您在子 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

相關內容