Как туда и обратно ассоциативный массив Bash в текстовый файл?

9

Я хочу запомнить ассоциативный массив между различными запусками скрипта. На данный момент у меня есть текстовый файл, содержащий одну пару ключ / значение:

(
[james]=bond
)

Это скрипт, который загружает его в ассоциативный массив, добавляет к нему, а затем выводит его таким образом, который можно перенаправить во второй файл:

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

тогда я могу запустить его как:

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

дающий

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

Все же это кажется очень неуклюжим. Есть ли более чистый способ сделать это?

simbo1905
источник
4
declare -p hash > fileсохранить hashассоциативный массив. source fileдля восстановления.
Стефан Шазелас
2
Наверное, должно быть arrays.bash...
mikeserv

Ответы:

10

In bash, declare -pможет использоваться для вывода определения переменной как готового к интерпретации кода оболочки, поэтому вы можете выполнять обновления файла с помощью:

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

Обратите внимание, что важно, чтобы файл создавался и исходил из одной и той же локали (как минимум, в той же LC_CTYPEкатегории).

Сценарий для отображения содержимого файла будет:

#! /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
Стефан Шазелас
источник
Ура для самоквалифицирующихся параметров! Но не будет ли более конкретная строка ошибки более полезной?
mikeserv
@mikeserv, конечно, но это не главное. Обязательно добавьте правильную проверку синтаксиса. Можно также захотеть проверить наличие четного числа аргументов после имени файла (или использовать нечетный одиночный аргумент в качестве средства для удаления одного элемента).
Стефан Шазелас
Я не знаю ... Может быть, не просите меня отредактировать ... Вы не должны приглашать вампиров ... Но то, что сделано, я думаю, сделано.
mikeserv
ой, извини. Думаю, я не должен был понимать это буквально? Я сделал то, что вы просили, и сделал его немного более надежным, не усложняя его.
mikeserv
2
@ ec2011, с последними версиями bash(более поздними, чем было доступно на момент написания ответа) вы сможете использовать readarray -td '' arrayдля чтения записей, разделенных NUL, в обычный массив, а затем преобразовать его в ассоциативный массив.
Стефан