Я думаю, ти запитуєш дві різні речі там.
Чи є спосіб зробити баш друкувати цю інформацію без циклу?
Так, але вони не такі гарні, як просто використання циклу.
Чи є більш чистий спосіб отримати / надрукувати лише ключ = частина вартості виводу?
Так, 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.