Простий фокус з одним рядком для демпінгу масиву
Я додав одне значення з пробілами:
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рядок за рядком.
Налаштування
Це можна налаштувати за допомогою -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)щоб перетворити його в масив.