如何在全球范围内声明-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

相关内容