How to reverse array in bash onliner FOR loop?

_arr+=( '"${_arrev} is an actual "${array[@]}"' )  ⏎
_arr+=( '"${_arrev} is created as a result"' )
_arr+=( '"of reversing the key order in"' )
_arr+=( '"this "${_arr}. It handles zsh and"' )
_arr+=( '"bash arrays intelligently by tracking"' )
_arr+=( '"shell "$ENV." quotes=fine ( i hope ) "' )

. <<REVERSE /dev/stdin                    ⏎
    _arrev=( $(: $((l=${#_arr[@]}${ZSH_VERSION++1})) ; printf '"${_arr[$(('$l'-%d))]}" ' `seq 1 $l`) )
REVERSE

echo ; printf %s\\n ${_arrev}

"shell "$ENV." quotes=fine ( i hope ) "
"bash arrays intelligently by tracking"
"this "${_arr}. It handles zsh and"
"of reversing the key order in"
"${_arrev} is created as a result"
"${_arrev} is an actual "${array[@]}"

This should handle any possible array, I think.

If you're interested in what's going on up there, I suggest you have a look here first. Then maybe here, definitely here, and, if you've got the time, here and here.

In all of those answers I discuss different aspects of the here-document (and in many others) which you can use to your advantage. For instance I discuss twice-evaluating variables, which is done above, and in one declare a function that globally declares another function named "_$1" in just 5 or 6 lines - most of which were _$1() { func body ; }. It's pretty handy if you use it correctly.

Regarding the auto-switch between bash/zsh, well that's something else, but very simple as well. See here.


You can use tac, which is an opposite of cat in sense that it reverses the lines.

MYARRAY=("one" "two" "three" "four")
for item in "$MYARRAY"; do
   echo "$item"; 
done | tac

# four
# three
# two
# one

You can use the C-style for loop:

for (( idx=${#MYARRAY[@]}-1 ; idx>=0 ; idx-- )) ; do
    echo "${MYARRAY[idx]}"
done

For an array with "holes", the number of elements ${#arr[@]} doesn't correspond to the index of the last element. You can create another array of indices and walk it backwards in the same way:

#! /bin/bash
arr[2]=a
arr[7]=b

echo ${#arr[@]}  # only 2!!

indices=( ${!arr[@]} )
for ((i=${#indices[@]} - 1; i >= 0; i--)) ; do
    echo "${arr[indices[i]]}"
done

Tags:

Bash