Is there a way to print an entire array ([key]=value) without looping over all elements?
Assume I have created an array with some elements:
declare -A array
array=([a1]=1 [a2]=2 ... [b1]=bbb ... [f500]=abcdef)
I can print back the entire array with
for i in "${!array[@]}"
do
echo "${i}=${array[$i]}"
done
However, it seems bash already knows how to get all array elements in one "go" – both keys ${!array[@]}
and values ${array[@]}
.
Is there a way to make bash print this info without the loop?
Edit:
typeset -p array
does that!
However I can't remove both prefix and suffix in a single substitution:
a="$(typeset -p array)"
b="${a##*(}"
c="${b%% )*}"
Is there a cleaner way to get/print only the key=value portion of the output?
Best Answer
I think you're asking two different things there.
Yes, but they are not as good as just using the loop.
Yes, the
for
loop. It has the advantages that it doesn't require external programs, is straightforward, and makes it rather easy to control the exact output format without surprises.Any solution that tries to handle the output of
declare -p
(typeset -p
) has to deal with a) the possibility of the variables themselves containing parenthesis or brackets, b) the quoting thatdeclare -p
has to add to make it's output valid input for the shell.For example, your expansion
b="${a##*(}"
eats some of the values, if any key/value contains an opening parenthesis. This is because you used##
, which removes the longest prefix. Same forc="${b%% )*}"
. Though you could of course match the boilerplate printed bydeclare
more exactly, you'd still have a hard time if you didn't want all the quoting it does.This doesn't look very nice unless you need it.
With the
for
loop, it's easier to choose the output format as you like:From there, it's also simple to change the output format otherwise (remove the brackets around the key, put all key/value pairs on a single line...). If you need quoting for something other than the shell itself, you'll still need to do it by yourself, but at least you have the raw data to work on. (If you have newlines in the keys or values, you are probably going to need some quoting.)
With a current Bash (4.4, I think), you could also use
printf "[%s]=%s" "${x@Q}" "${array[$x]@Q}"
instead ofprintf "%q=%q"
. It produces a somewhat nicer quoted format, but is of course a bit more work to remember to write. (And it quotes the corner case of@
as array key, which%q
doesn't quote.)If the for loop seems too weary to write, save it a function somewhere (without quoting here):
And then just use that:
Works with indexed arrays, too: