Я думаю, ти запитуєш дві різні речі там.
Чи є спосіб зробити баш друкувати цю інформацію без циклу?
Так, але вони не такі гарні, як просто використання циклу.
Чи є більш чистий спосіб отримати / надрукувати лише ключ = частина вартості виводу?
Так, for
петля. Він має ті переваги, що не вимагає зовнішніх програм, є простим і дозволяє легко контролювати точний вихідний формат без сюрпризів.
Будь-яке рішення, яке намагається обробити висновок declare -p
( typeset -p
), має мати справу з a) можливістю самих змінних, що містять дужки або дужки, b) цитування, declare -p
яке слід додати, щоб зробити його вихід правильним введенням для оболонки.
Наприклад, розширення b="${a##*(}"
з'їдає деякі значення, якщо якийсь ключ / значення містить круглі дужки. Це тому, що ви використовували ##
, що видаляє найдовший префікс. Те саме для c="${b%% )*}"
. Хоча, звичайно, ви могли б declare
точно відповідати котлові, надрукованій більш точно, вам все одно буде важко, якби ви не хотіли, щоб усі цитування цього були.
Це не виглядає дуже приємно, якщо вам це не потрібно.
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
За допомогою for
циклу простіше вибрати вихідний формат, як вам подобається:
# without quoting
$ for x in "${!array[@]}"; do printf "[%s]=%s\n" "$x" "${array[$x]}" ; done
[def]="foo bar"
[abc]='foobar'
# with quoting
$ for x in "${!array[@]}"; do printf "[%q]=%q\n" "$x" "${array[$x]}" ; done
[def]=\"foo\ bar\"
[abc]=\'foobar\'
Звідти також просто змінити вихідний формат інакше (видаліть дужки навколо клавіші, покладіть всі пари клавіш / значень на один рядок ...). Якщо вам потрібно цитувати щось інше, ніж саму оболонку, вам все одно доведеться робити це самостійно, але принаймні у вас є необроблені дані, над якими можна працювати. (Якщо у вас є нові рядки в ключах або значеннях, вам, ймовірно, знадобиться деяке цитування.)
З поточним Bash (4.4, я думаю) ви також можете використовувати printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
замість printf "%q=%q"
. Він створює дещо приємніший формат котирування, але, звичайно, трохи більше роботи, що потрібно пам'ятати, щоб написати. (І він цитує кутовий випадок @
як ключ масиву, який %q
не цитує.)
Якщо цикл for здається занадто стомленим для запису, збережіть його десь (не цитуючи тут):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
А потім просто використовуйте це:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
Працює і з індексованими масивами:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
printf ...%q...
варіанту не підходить для повторного введення в оболонку, якщо масив має@
ключ, оскільки% q не цитує його іa=([@]=value)
є синтаксичною помилкою вbash
.