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