Je pense que vous demandez deux choses différentes.
Existe-t-il un moyen de faire bash imprimer ces informations sans la boucle?
Oui, mais ils ne sont pas aussi efficaces que l'utilisation de la boucle.
Existe-t-il un moyen plus propre d'obtenir / imprimer uniquement la partie clé = valeur de la sortie?
Oui, la for
boucle. Il a l'avantage de ne pas nécessiter de programmes externes, est simple et facilite le contrôle du format de sortie exact sans surprise.
Toute solution qui essaie de gérer la sortie de declare -p
( typeset -p
) doit faire face à a) la possibilité que les variables elles-mêmes contiennent des parenthèses ou des crochets, b) la citation qui declare -p
doit être ajoutée pour que sa sortie soit valide pour le shell.
Par exemple, votre expansion b="${a##*(}"
mange certaines des valeurs, si une clé / valeur contient une parenthèse ouvrante. En effet, vous avez utilisé ##
, ce qui supprime le préfixe le plus long . Pareil pour c="${b%% )*}"
. Bien que vous puissiez bien sûr faire correspondre declare
plus exactement le passe-partout imprimé , vous auriez encore du mal si vous ne vouliez pas tous les devis.
Cela n'a pas l'air très agréable sauf si vous en avez besoin.
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
Avec la for
boucle, il est plus facile de choisir le format de sortie comme vous le souhaitez:
# 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\'
À partir de là, il est également simple de changer le format de sortie sinon (supprimez les crochets autour de la clé, mettez toutes les paires clé / valeur sur une seule ligne ...). Si vous avez besoin de citer autre chose que le shell lui-même, vous devrez toujours le faire vous-même, mais au moins vous avez les données brutes sur lesquelles travailler. (Si vous avez des sauts de ligne dans les clés ou les valeurs, vous aurez probablement besoin de quelques citations.)
Avec un Bash actuel (4.4, je pense), vous pouvez également utiliser à la printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
place de printf "%q=%q"
. Il produit un format cité un peu plus agréable, mais est bien sûr un peu plus de travail à retenir pour écrire. (Et il cite le cas du coin de la @
clé de tableau, qui %q
ne cite pas.)
Si la boucle for semble trop fatiguée pour être écrite, enregistrez-la quelque part (sans citer ici):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
Et puis il suffit de l'utiliser:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
Fonctionne également avec les tableaux indexés:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
printf ...%q...
variante ne convient pas pour une réintroduction dans le shell si le tableau a une@
clé car% q ne la cite pas eta=([@]=value)
est une erreur de syntaxe dansbash
.