Saya pikir Anda menanyakan dua hal berbeda di sana.
Apakah ada cara untuk membuat bash mencetak info ini tanpa loop?
Ya, tetapi mereka tidak sebagus hanya menggunakan loop.
Apakah ada cara yang lebih bersih untuk mendapatkan / mencetak hanya bagian kunci = nilai dari output?
Ya itu for
simpulnya. Ini memiliki kelebihan yang tidak memerlukan program eksternal, mudah, dan membuatnya lebih mudah untuk mengontrol format output yang tepat tanpa kejutan.
Solusi apa pun yang mencoba menangani output dari declare -p
(typeset -p
) harus berurusan dengan a) kemungkinan variabel itu sendiri mengandung tanda kurung atau tanda kurung, b) kutipan yang declare -p
harus ditambahkan untuk membuat output itu valid input untuk shell.
Misalnya, ekspansi Anda b="${a##*(}"
memakan beberapa nilai, jika ada kunci / nilai yang berisi tanda kurung buka. Ini karena Anda menggunakan ##
, yang menghilangkan awalan terpanjang . Sama untukc="${b%% )*}"
. Meskipun tentu saja Anda dapat mencocokkan pelat tungku yang dicetak dengan declare
lebih tepat, Anda masih akan mengalami kesulitan jika Anda tidak ingin semua kutipannya cocok.
Ini tidak terlihat bagus kecuali Anda membutuhkannya.
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
Dengan for
loop, lebih mudah untuk memilih format output sesuka Anda:
# 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\'
Dari sana, juga mudah untuk mengubah format output jika tidak (hapus tanda kurung di sekitar kunci, letakkan semua pasangan kunci / nilai pada satu baris ...). Jika Anda perlu mengutip sesuatu selain dari shell itu sendiri, Anda masih perlu melakukannya sendiri, tetapi setidaknya Anda memiliki data mentah untuk dikerjakan. (Jika Anda memiliki baris baru di kunci atau nilai, Anda mungkin perlu mengutip.)
Dengan Bash saat ini (4,4, saya pikir), Anda juga bisa menggunakan printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
bukan printf "%q=%q"
. Ini menghasilkan format kutipan yang agak lebih bagus, tetapi tentu saja sedikit lebih banyak pekerjaan yang perlu diingat untuk menulis. (Dan itu mengutip kasus sudut @
sebagai kunci array, yang %q
tidak mengutip.)
Jika for for tampaknya terlalu lelah untuk ditulis, simpan fungsi di suatu tempat (tanpa mengutip di sini):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
Dan kemudian gunakan itu:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
Bekerja dengan array yang diindeks juga:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
printf ...%q...
varian Anda tidak cocok untuk reinput ke shell jika array memiliki@
kunci karena% q tidak mengutipnya dana=([@]=value)
merupakan kesalahan sintaksis dalambash
.