Eu acho que você está perguntando duas coisas diferentes lá.
Is there a way to make bash print this info without the loop?
Sim, mas eles não são tão bons quanto usar o loop.
Is there a cleaner way to get/print only the key=value portion of the output?
Sim, o loop for
. Ele tem as vantagens de não exigir programas externos, é simples e facilita bastante o controle do formato de saída exato sem surpresas.
Qualquer solução que tente manipular a saída de declare -p
( typeset -p
)
tem que lidar com a) a possibilidade de as variáveis conterem parênteses ou colchetes, b) as citações que declare -p
tem que adicionar para fazer sua saída válida para o shell.
Por exemplo, sua expansão b="${a##*(}"
come alguns dos valores, se qualquer chave / valor contiver um parêntese de abertura. Isso porque você usou ##
, que remove o prefixo maior . O mesmo para c="${b%% )*}"
. Embora você possa, é claro, combinar exatamente com o clichê impresso por declare
, você ainda teria dificuldades se não quisesse todas as citações.
Isso não parece muito bom, a menos que você precise.
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
Com o for
loop, é mais fácil escolher o formato de saída como você gosta:
# 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\'
A partir daí, também é simples alterar o formato de saída (remova os colchetes ao redor da chave, coloque todos os pares chave / valor em uma única linha ...). Se você precisar de citar algo diferente do próprio shell, ainda precisará fazer isso sozinho, mas pelo menos terá os dados brutos para trabalhar. (Se você tiver novas linhas nas chaves ou valores, provavelmente precisará de algumas citações.)
Com um Bash atual (4.4, eu acho), você também pode usar printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
em vez de printf "%q=%q"
. Ele produz um formato um pouco mais agradável, mas é claro que é um pouco mais trabalhoso lembrar de escrever. (e cita o caso de canto de @
como chave de matriz, que %q
não cita.)
Se o loop for parecer muito cansado para escrever, salve-o em alguma parte (sem citar aqui):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
E então use isso:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
Funciona com matrizes indexadas também:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc