Como declarar -A MYASSOCIATIVEARRY globalmente?

Como declarar -A MYASSOCIATIVEARRY globalmente?

Eu tenho exatamente o mesmo problema descrito nesta postagem do SO ("a string da chave da matriz associativa bash com dois pontos está apresentando erro"):https://stackoverflow.com/q/40406187/10639803

A solução é usar, declare -Amas depois de fazer isso, meu array associativo deixa de ser global.

Existe uma maneira dedeclare -A eter isso global?

ATUALIZAÇÃO: tentei declare -gAconforme descrito aqui:https://stackoverflow.com/a/21151984/10639803mas não funciona para mim por algum motivo: assim que sai do loop que preenche meu array associativo (hashmap), o array é desativado.

Aqui está o código bash real (os comandos echo dentro do loop são para verificar se os valores foram realmente extraídos e atribuídos):

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

Responder1

O problema que você está vendo não tem nada a ver com a declaração da variável. É porque você está definindo a variável em um subshell e esperando que seus valores estejam disponíveis no pai.

Você pode ver esse efeito aqui, usando a mesma estrutura do seu código, mas com um exemplo muito mais simples:

a=""
echo find | while read item; do a="$item"; done
echo "a=$a"

Felizmente, ao usar, bashexiste uma solução rápida disponível, reescrevendo o código em um formato diferente:

a=""
while read item; do a="$item"; done < <( echo find )
echo "a=$a"

Em código real, use while IFS= read -r itempara garantir que itemreceba entrada não processada. Omiti as proteções para o que espero ser clareza nos exemplos.


Nos comentários desta resposta você solicitou uma versão revisada do seu código. Não posso testá-lo, por isso hesitei em colocá-lo aqui, mas deve ficar assim:

#!/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

informação relacionada