Sanırım orada iki farklı şey soruyorsun.
Bu bilgiyi döngü olmadan bash yapmanın bir yolu var mı?
Evet, ama sadece döngüyü kullanmak kadar iyi değiller.
Çıktının yalnızca anahtar = değer kısmını almanın / yazdırmanın daha temiz bir yolu var mı?
Evet, for
döngü. Harici programlar gerektirmediği, basit olduğu ve kesin çıktı formatını sürprizler olmadan kontrol etmeyi oldukça kolaylaştırdığı avantajları vardır.
declare -p
( typeset -p
) Çıktısını ele almaya çalışan herhangi bir çözüm, a) parantez veya parantez içeren değişkenlerin kendileriyle ilgilenmek zorundadır, b) declare -p
kabuğun çıktısı için geçerli girdi olmasını sağlamak için eklenmesi gereken alıntı .
Örneğin, b="${a##*(}"
herhangi bir anahtar / değer bir açılış parantezi içeriyorsa , genişletmeniz değerlerin bazılarını yer. Bunun nedeni ##
, en uzun öneki kaldıran kullanmanızdır . Aynı c="${b%% )*}"
. Tabii ki tarafından basılmış olan kazan plakasını eşleştirebilirsiniz.declare
daha tam olarak , yaptığı tüm alıntıları istemiyorsanız yine de zor zamanlarınız olurdu.
İhtiyacınız olmadığı sürece bu çok hoş görünmüyor.
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
for
Döngü ile çıktı biçimini istediğiniz gibi seçmek daha kolaydır:
# 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\'
Oradan , çıktı biçimini değiştirmek de basittir (anahtarın etrafındaki köşeli parantezleri kaldırın, tüm anahtar / değer çiftlerini tek bir satıra koyun ...). Kabuğun kendisinden başka bir şey için alıntı yapmanız gerekiyorsa, yine de bunu kendiniz yapmanız gerekir, ancak en azından üzerinde çalışmak için ham verilere sahipsiniz. (Anahtarlarda veya değerlerde yeni satırlarınız varsa, muhtemelen biraz alıntı yapmanız gerekecektir.)
Mevcut bir Bash (4.4, sanırım) printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
yerine, kullanabilirsiniz printf "%q=%q"
. Biraz daha hoş bir alıntı biçimi üretir, ancak elbette yazmayı hatırlamak biraz daha fazla iş. (Ve köşe @
anahtarı olarak tırnak işareti için %q
alıntı yapmaz.)
For döngüsü yazmak için çok yorgun görünüyorsa, bir yere bir işlev kaydedin (burada alıntı yapmadan):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
Ve sonra sadece bunu kullanın:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
Dizine alınmış dizilerle de çalışır:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
printf ...%q...
Eğer dizinin@
% q anahtarı belirtmediği vea=([@]=value)
sözdizimi hatası olduğu için dizinin bir anahtarı varsa, varyantınızın çıktısının kabuğa yeniden giriş için uygun olmadığını unutmayınbash
.