Myślę, że pytasz o dwie różne rzeczy.
Czy istnieje sposób, aby bash wydrukował te informacje bez pętli?
Tak, ale nie są tak dobre, jak zwykła pętla.
Czy istnieje prostszy sposób na uzyskanie / wydrukowanie tylko części klucz = wartość wyniku?
Tak, for
pętla. Ma to tę zaletę, że nie wymaga programów zewnętrznych, jest proste i sprawia, że kontrolowanie dokładnego formatu wyjściowego jest dość łatwe bez niespodzianek.
Każde rozwiązanie, które próbuje obsłużyć dane wyjściowe declare -p
( typeset -p
), musi dotyczyć: a) możliwości samych zmiennych zawierających nawiasy lub nawiasy, b) cytowania, żedeclare -p
należy dodać, aby dane wyjściowe były prawidłowe dla powłoki.
Na przykład twoje rozwinięcie b="${a##*(}"
zjada niektóre wartości, jeśli dowolny klucz / wartość zawiera nawias otwierający. Jest tak, ponieważ użyłeś ##
, który usuwa najdłuższy prefiks. To samo dotyczy c="${b%% )*}"
. Chociaż możesz oczywiście dopasować declare
dokładnie wydrukowany szablon , nadal będziesz miał trudności, jeśli nie chcesz wszystkich cytatów.
Nie wygląda to zbyt ładnie, chyba że jest to potrzebne.
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
Dzięki for
pętli łatwiej jest wybrać format wyjściowy, jak chcesz:
# 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\'
Stamtąd można również w prosty sposób zmienić format wyjściowy (usuń nawiasy wokół klucza, umieść wszystkie pary klucz / wartość w jednym wierszu ...). Jeśli potrzebujesz cytowania czegoś innego niż sama powłoka, nadal musisz to zrobić sam, ale przynajmniej masz surowe dane do pracy. (Jeśli masz nowe znaki w kluczach lub wartościach, prawdopodobnie będziesz potrzebować cytowania).
Przy obecnej wersji Bash (wydaje mi się, że 4.4) możesz także użyć printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
zamiast printf "%q=%q"
. Tworzy nieco ładniejszy format cytowany, ale oczywiście jest trochę więcej pracy do zapamiętania, aby pisać. (I cytuje przypadek narożny @
jako klucz tablicy, który %q
nie cytuje.)
Jeśli pętla for wydaje się zbyt zmęczona, aby pisać, zapisz gdzieś funkcję (bez cytowania tutaj):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
A następnie użyj tego:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
Działa również z indeksowanymi tablicami:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
printf ...%q...
wariantu nie nadaje się do ponownego włożenia do powłoki, jeśli tablica ma@
klucz, ponieważ% q go nie zacytuje ia=([@]=value)
jest to błąd składniowy wbash
.