¿Cómo hacer un viaje de ida y vuelta de una matriz asociativa bash a un archivo de texto?

9

Quiero memorizar una matriz asociativa entre diferentes ejecuciones de script. Lo que tengo hasta ahora es que dado un archivo de texto que contiene un par clave / valor:

(
[james]=bond
)

Es un script para cargar eso en una matriz asociativa, agregarlo y luego repetirlo de una manera que se pueda redirigir a un segundo archivo:

#!/bin/bash
file=`cat $1`
key=$2
value=$3
declare -A row="$file"
row[$key]=$value
echo "("
for server in "${!row[@]}"
    do echo "[$server]=${row[$server]}"; done
echo ")"

entonces puedo ejecutarlo como:

./arrays.sh file1 honey rider > file2 ; mv file2 file1

Dando

(
[james]=bond
[honey]=rider
)

Sin embargo, parece muy torpe. ¿Hay una forma más limpia de hacer esto?

simbo1905
fuente
44
declare -p hash > filepara guardar la hashmatriz asociativa. source filerestaurar.
Stéphane Chazelas
2
Probablemente debería ser arrays.bash...
mikeserv

Respuestas:

10

En bash, declare -pse puede usar para volcar la definición de una variable como código de shell listo para ser interpretado, por lo que puede hacer actualizaciones al archivo con:

#! /bin/bash -
file=${1?}; shift
declare -A row
source -- "$file" || exit
while [ "$#" -ge 2 ]; do
  row[$1]=$2
  shift 2
done
declare -p row > "$file"

Tenga en cuenta que es importante que el archivo se genere y obtenga en la misma configuración regional (al menos, la misma LC_CTYPEcategoría).

Un script para mostrar el contenido del archivo sería:

#! /bin/bash -
file=${1?}; shift
declare -A row
source -- "$file"
for i in "${!row[@]}"
do
  printf 'key  : %s\n' "$i"
  printf 'value: %s\n' "${row[$i]}"
done
Stéphane Chazelas
fuente
¡Hurra por los parámetros de autocalificación! ¿Pero una cadena de error más específica no sería más útil?
mikeserv
@mikeserv, claro, pero eso está más allá del punto de la respuesta. Por supuesto, agregue la verificación de sintaxis adecuada según corresponda. También es posible que desee verificar que haya un número par de argumentos después del nombre del archivo (o usar el argumento único impar como un medio para eliminar un solo elemento).
Stéphane Chazelas
No sé ... Tal vez no me pidas que edite ... Se supone que no debes invitar a los vampiros ... Pero lo hecho, hecho está, supongo.
mikeserv
Oh, lo siento. ¿Supongo que no debería haber tomado eso literalmente? Hice lo que me pediste y lo hice un poco más robusto sin complicarlo.
mikeserv
2
@ ec2011, con versiones recientes de bash(más reciente de la que estaba disponible en el momento en que se escribió la respuesta) que podría usar readarray -td '' arraypara leer registros delimitados por NUL en una matriz regular y luego convertirla en una matriz asociativa.
Stéphane Chazelas