This might be the ugliest Bash code I've ever written, but...
IPv4_first=1.1.1.1
IPv4_second=2.2.2.2
IPv4_third=3.3.3.3
names=(${!IPv4_@})
eval "IPv4_all=(${names[@]/#/$})"
printf "'%s'\n" "${IPv4_all[@]}"
Look Ma, no loop!
${names[@]/#/$}
prepends $
to the start of every element of the array, by matching an empty string anchored to the start of each element. That gives an array of variable dereferences, which we can expand inside eval
to get the variable references inside the array initialiser. These need to be two separate lines because you can't apply multiple parameter expansions at the same time.
The output is:
'1.1.1.1'
'2.2.2.2'
'3.3.3.3'
as expected.
It's possible to replace the line with:
IPv4_all=($(eval "echo ${names[@]/#/$}"))
rather than eval
ling the array assignment. I'm not sure whether that's any better or not.
If your variable values might contain spaces or other IFS characters, you can change the eval:
eval "IPv4_all=($(printf '"$%s" ' "${names[@]}"))"
That properly double-quotes all the variable dereferences.