Eu acho que você está perguntando duas coisas diferentes lá.
Existe uma maneira de fazer o bash imprimir essas informações sem o loop?
Sim, mas eles não são tão bons quanto usar o loop.
Existe uma maneira mais limpa de obter / imprimir apenas a parte key = value da saída?
Sim, o for
laço. Tem as vantagens de não exigir programas externos, é simples e facilita o controle exato do formato de saída sem surpresas.
Qualquer solução que tente manipular a saída de declare -p
( typeset -p
) deve lidar com a) a possibilidade de as próprias variáveis conterem parênteses ou colchetes, b) a citação que declare -p
deve ser adicionada para tornar sua entrada válida de saída para o shell.
Por exemplo, sua expansão b="${a##*(}"
consome alguns valores, se alguma chave / valor contiver um parêntese de abertura. Isso ocorre porque você usou ##
, o que remove o prefixo mais longo . O mesmo para c="${b%% )*}"
. Embora você possa, obviamente, corresponder ao padrão impresso de maneira declare
mais exata, você ainda teria dificuldade 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 de chave / valor em uma única linha ...). Se você precisar 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 nos valores, provavelmente precisará de algumas aspas.)
Com um Bash atual (4.4, eu acho), você também pode usar em printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
vez de printf "%q=%q"
. Ele produz um formato citado um pouco melhor, mas é obviamente um pouco mais trabalhoso para se lembrar de escrever. (E cita a caixa de canto @
como chave de matriz, que %q
não cita.)
Se o loop for parecer muito cansativo para escrever, salve uma função em algum lugar (sem citar aqui):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
E então basta usar isso:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
Também funciona com matrizes indexadas:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
printf ...%q...
variante não é adequada para reinicialização no shell se a matriz tiver uma@
chave, pois% q não a cita ea=([@]=value)
for um erro de sintaxebash
.