Creo que estás preguntando dos cosas diferentes allí.
¿Hay alguna manera de hacer que bash imprima esta información sin el bucle?
Sí, pero no son tan buenos como simplemente usar el bucle.
¿Hay una forma más limpia de obtener / imprimir solo la parte clave = valor de la salida?
Sí, el for
bucle. Tiene las ventajas de que no requiere programas externos, es sencillo y facilita el control del formato de salida exacto sin sorpresas.
Cualquier solución que intente manejar la salida de declare -p
( typeset -p
) tiene que tratar con a) la posibilidad de que las variables contengan paréntesis o corchetes, b) la cita quedeclare -p
debe agregar para hacer que su salida sea una entrada válida para el shell.
Por ejemplo, su expansión b="${a##*(}"
come algunos de los valores, si alguna clave / valor contiene un paréntesis de apertura. Esto se debe a que usó ##
, lo que elimina el prefijo más largo . Lo mismo para c="${b%% )*}"
. Aunque, por supuesto, podría igualar la plantilla impresa con declare
más precisión, aún le costaría mucho trabajo si no quisiera todas las citas.
Esto no se ve muy bien a menos que lo necesite.
$ declare -A array=([abc]="'foobar'" [def]='"foo bar"')
$ declare -p array
declare -A array='([def]="\"foo bar\"" [abc]="'\''foobar'\''" )'
Con el for
bucle, es más fácil elegir el formato de salida que desee:
# 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 de ahí, también es simple. cambiar el formato de salida de lo contrario (quite los corchetes alrededor de la clave, coloque todos los pares clave / valor en una sola línea ...). Si necesita citar algo diferente al shell en sí, deberá hacerlo usted mismo, pero al menos tiene los datos sin procesar para trabajar. (Si tiene nuevas líneas en las claves o valores, probablemente necesitará algunas citas).
Con un Bash actual (4.4, creo), también podría usarlo en printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
lugar de printf "%q=%q"
. Produce un formato citado algo más agradable, pero por supuesto es un poco más trabajo para recordar escribir. (Y cita el caso de la esquina @
como clave de matriz, que %q
no cita).
Si el bucle for parece demasiado cansado para escribir, guárdelo como una función en algún lugar (sin citar aquí):
printarr() { declare -n __p="$1"; for k in "${!__p[@]}"; do printf "%s=%s\n" "$k" "${__p[$k]}" ; done ; }
Y luego solo usa eso:
$ declare -A a=([a]=123 [b]="foo bar" [c]="(blah)")
$ printarr a
a=123
b=foo bar
c=(blah)
También funciona con matrices indexadas:
$ b=(abba acdc)
$ printarr b
0=abba
1=acdc
printf ...%q...
variante no es adecuada para reiniciar al shell si la matriz tiene una@
clave como% q no la cita ya=([@]=value)
es un error de sintaxisbash
.