0

So, Let's say i have an array arr, with two element in it:

read -a arr <<< "$@"

where i would then either use it in a function or script and input two string or element like so:

read_me() {
read -a arr <<< "$@"
}
read_me "first test"

Now i already know how to get through all the elements of an array:

for i in "${arr[@]}"
do
    echo "$i" # where i do something with the respective element of said array.
done

But that only do it using the normal/original order in which the element were added to the previously mentioned array... Of course, i also know how to get the elements of an array in reverse order:

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

Both of these ways work as intended. Problem though, is that i need both the normal and the reverse order on the same loop. Mostly so i wouldn't need to do this:

echo "${arr[0]}" "${arr[1]}"
echo "${arr[1]}" "${arr[0]}"

How could i do this in a single loop?

2
  • Given that the array only contains two elements, I'm not even sure why there needs to be an array, or why the last piece of code is not good enough.
    – Kusalananda
    Apr 25, 2021 at 20:29
  • Because if i were to add more elements to previously mentioned array, then the last piece of code would need to be later expanded :) @Kusalananda which is why I'm trying to make a loop (single loop encompassing what i already know how to do) Apr 25, 2021 at 20:30

1 Answer 1

4
array=( 1 2 3 a b c )

for i in "${!array[@]}"; do
    j=$(( ${#array[@]} - i - 1 ))
    printf '%s\t%s\n' "${array[i]}" "${array[j]}"
done

Output:

1       c
2       b
3       a
a       3
b       2
c       1

In short, there is nothing stopping you from traversing the array in any order and at the same time calculate a new index from the current index and use that too.


In comments to the question, there is a suggestion for the following arithmetic loop:

for (( i = 0, j = ${#array[@]} - 1; i < ${#array[@]}; ++i, --j ))
do
    printf '%s\t%s\n' "${array[i]}" "${array[j]}"
done

This uses the fact that the comma operator can be used in the initialization and update parts of the loop header to maintain two separate loop variables.


Depending on what you want to achieve and depending on what your actual array values are, you may also get away with using tac:

$ paste <( printf '%s\n' "${array[@]}" ) <( printf '%s\n' "${array[@]}" | tac )
1       c
2       b
3       a
a       3
b       2
c       1
1
  • Yeah, this look much better than what i had in mind (which was two for loop). Thanks a lot :) Apr 25, 2021 at 20:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .