Tengo exactamente el mismo problema que se describe en esta publicación SO ("la cadena de clave de matriz asociativa de bash con dos puntos da error"):https://stackoverflow.com/q/40406187/10639803
La solución es usar declare -A
pero una vez que hago esto, mi matriz asociativa deja de ser global.
¿Hay alguna manera dedeclare -A
y¿Tenerlo global?
ACTUALIZACIÓN: Lo intenté declare -gA
como se describe aquí:https://stackoverflow.com/a/21151984/10639803pero no me funciona por alguna razón: tan pronto como salgo del bucle que llena mi matriz asociativa (hashmap), la matriz se desarma.
Aquí está el código bash real (los comandos de eco dentro del bucle son para verificar que los valores realmente se extraigan y asignen):
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
Respuesta1
El problema que estás viendo no tiene nada que ver con la declaración de la variable. Es porque está configurando la variable en una subcapa y espera que sus valores estén disponibles en la capa principal.
Puedes ver este efecto aquí, usando la misma estructura que tu código pero con un ejemplo mucho más simple:
a=""
echo find | while read item; do a="$item"; done
echo "a=$a"
Afortunadamente, cuando se usa, bash
hay una solución rápida disponible al reescribir el código en una forma diferente:
a=""
while read item; do a="$item"; done < <( echo find )
echo "a=$a"
En código real, utilícelo while IFS= read -r item
para asegurarse de item
recibir entradas sin procesar. He omitido las protecciones por lo que espero sea claridad en los ejemplos.
En los comentarios de esta respuesta, solicitó una versión revisada de su código. No puedo probarlo, por eso dudé en ponerlo aquí en primer lugar, pero debería verse así:
#!/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