Простой однострочный трюк для дампа массива
Я добавил одно значение с пробелами:
foo=()
foo[12]="bar"
foo[42]="foo bar baz"
foo[35]="baz"
Я, для быстрого сброса удармассивы или ассоциативные массивы я использую
Эта однострочная команда:
paste <(printf "%s\n" "${!foo[@]}") <(printf "%s\n" "${foo[@]}")
Окажет:
12 bar
35 baz
42 foo bar baz
Разъяснения
printf "%s\n" "${!foo[@]}"напечатает все ключи, разделенные новой строкой ,
printf "%s\n" "${foo[@]}"напечатает все значения, разделенные новой строкой ,
paste <(cmd1) <(cmd2)объединит вывод cmd1и cmd2построчно.
Tunning
Это может быть настроено -dпереключателем:
paste -d : <(printf "%s\n" "${!foo[@]}") <(printf "%s\n" "${foo[@]}")
12:bar
35:baz
42:foo bar baz
или даже:
paste -d = <(printf "foo[%s]\n" "${!foo[@]}") <(printf "'%s'\n" "${foo[@]}")
foo[12]='bar'
foo[35]='baz'
foo[42]='foo bar baz'
Ассоциативный массив будет работать так же:
declare -A bar=([foo]=snoopy [bar]=nice [baz]=cool [foo bar]='Hello world!')
paste -d = <(printf "bar[%s]\n" "${!bar[@]}") <(printf '"%s"\n' "${bar[@]}")
bar[foo bar]="Hello world!"
bar[foo]="snoopy"
bar[bar]="nice"
bar[baz]="cool"
Проблема с переводом строки или специальными
К сожалению, есть по крайней мере одно условие, заставляющее это больше не работать: когда переменная содержит символ новой строки:
foo[17]=$'There is one\nnewline'
Команда pasteбудет объединяться строка за строкой, поэтому вывод будет неправильным:
paste -d = <(printf "foo[%s]\n" "${!foo[@]}") <(printf "'%s'\n" "${foo[@]}")
foo[12]='bar'
foo[17]='There is one
foo[35]=newline'
foo[42]='baz'
='foo bar baz'
Для этой работы вы можете использовать %qвместо %sвторой printfкоманды (и кавычки):
paste -d = <(printf "foo[%s]\n" "${!foo[@]}") <(printf "%q\n" "${foo[@]}")
Сделает идеально:
foo[12]=bar
foo[17]=$'There is one\nnewline'
foo[35]=baz
foo[42]=foo\ bar\ baz
От man bash:
%q causes printf to output the corresponding argument in a
format that can be reused as shell input.
(a b c)чтобы преобразовать в массив.