Ich denke, Sie fragen dort zwei verschiedene Dinge.
Gibt es eine Möglichkeit, Bash dazu zu bringen, diese Informationen ohne die Schleife auszudrucken?
Ja, aber sie sind nicht so gut wie nur mit der Schleife.
Gibt es eine sauberere Methode, um nur den Teil key = value der Ausgabe abzurufen / auszudrucken?
Ja, die for
Schleife. Es hat den Vorteil, dass keine externen Programme erforderlich sind, es ist unkompliziert und es ist ziemlich einfach, das genaue Ausgabeformat ohne Überraschungen zu steuern.
Jede Lösung, die versucht, die Ausgabe von declare -p
( typeset -p
) zu verarbeiten, muss sich mit a) der Möglichkeit befassen, dass die Variablen selbst Klammern oder Klammern enthalten, b) dem Anführungszeichen, declare -p
das hinzugefügt werden muss, damit die Ausgabe für die Shell gültig ist.
Zum Beispiel b="${a##*(}"
frisst Ihre Erweiterung einige der Werte, wenn ein Schlüssel / Wert eine öffnende Klammer enthält. Dies liegt daran, dass Sie verwendet haben ##
, wodurch das längste Präfix entfernt wird. Gleiches gilt für c="${b%% )*}"
. Selbstverständlich könnten Sie das von Ihnen gedruckte Boilerplate declare
genauer zuordnen, aber es würde Ihnen immer noch schwer fallen, wenn Sie nicht alle Zitate wünschen, die es bietet.
Das sieht nicht sehr schön aus, wenn Sie es nicht brauchen.
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
Mit der for
Schleife ist es einfacher, das Ausgabeformat nach Belieben auszuwählen:
# 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\'
Von dort aus ist es auch einfach , das Ausgabeformat anderweitig zu ändern (entfernen Sie die Klammern um den Schlüssel, setzen Sie alle Schlüssel / Wert-Paare in eine einzelne Zeile ...). Wenn Sie ein Angebot für etwas anderes als die Shell selbst benötigen, müssen Sie es dennoch selbst erstellen, aber Sie haben zumindest die Rohdaten, an denen Sie arbeiten können. (Wenn Sie Zeilenumbrüche in den Schlüsseln oder Werten haben, müssen Sie wahrscheinlich etwas zitieren.)
Mit einem aktuellen Bash (4.4, glaube ich) könnte man auch printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
statt verwenden printf "%q=%q"
. Es erzeugt ein etwas schöneres zitiertes Format, aber es ist natürlich ein bisschen mehr Arbeit, sich daran zu erinnern, es zu schreiben. (Und es zitiert den Eckfall @
als Array-Schlüssel, der %q
nicht zitiert wird.)
Wenn die for-Schleife zum Schreiben zu müde erscheint, speichern Sie sie an einer beliebigen Stelle (ohne hier zu zitieren):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
Und dann benutze einfach das:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
Funktioniert auch mit indizierten Arrays:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
printf ...%q...
Variante nicht für die erneute Eingabe in die Shell geeignet ist, wenn das Array einen@
Schlüssel hat, da% q ihn nicht in Anführungszeichen setzt unda=([@]=value)
ein Syntaxfehler vorliegtbash
.