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