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 -A
mas depois de fazer isso, meu array associativo deixa de ser global.
Existe uma maneira dedeclare -A
eter isso global?
ATUALIZAÇÃO: tentei declare -gA
conforme 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, bash
existe 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 item
para garantir que item
receba 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