Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop over indices of sliced array in bash

I want to loop over the indices of an array starting on the second index. How can I do this?

I have tried:

myarray=( "test1" "test2" "test3" "test4")
for i in ${!myarray[@]:1}
do
    # I only print the indices to simplify the example
    echo $i 
done

But doesn't work.

Obviously this works:

myarray=( "test1" "test2" "test3" "test4")
myindices=("${!myarray[@]}")
for i in ${myindices[@]:1}
do
    echo $i
done

But I would like to combine everything in the for loop statement if possible.

like image 271
Carles Ràfols Avatar asked Oct 29 '25 16:10

Carles Ràfols


2 Answers

Use the # parameter length expansion:

myarray=( "test1" "test2" "test3" "test4")
for (( i=1;  i < ${#myarray[@]};  i++ ))
do
    # only print the indices to simplify the example
    echo $i 
done

Note that the ! indirect expansion operator is evidently not compatible with substring expansion since:

echo "${!myarray[@]:2}"

Produces an error code 1 and outputs to STDERR:

bash: test1 test2 test3 test4: bad substitution

At least for current versions of bash, v.4.4 and earlier. Unfortunately man bash doesn't make it sufficiently clear that substring expansion doesn't work with indirect expansion.

like image 191
agc Avatar answered Oct 31 '25 06:10

agc


I'd do it this way:

#!/usr/bin/env bash

myarray=('a' 'b' 'c' 'd')

start_index=2
# generate a null delimited list of indexes
printf '%s\0' "${!myarray[@]}" |
  # slice the indexes list 2nd entry to last
  cut --zero-terminated --delimiter='' --fields="${start_index}-" |
  # iterate the sliced indexes list
  while read -r -d '' i; do
    echo "$i"
  done

Output does not list first index 0 as expected:

1
2
3

Works as well with an associative array:

#!/usr/bin/env bash

typeset -A myassocarray=(["foo"]='a' ["bar"]='b' ["baz"]='c' ["qux"]='d')

start_index=2
# generate a null delimited list of indexes
printf '%s\0' "${!myassocarray[@]}" |
  # slice the indexes list 2nd entry to last
  cut --zero-terminated --delimiter='' --fields="${start_index}-" |
  # iterate the sliced indexes list
  while read -r -d '' k; do
    echo "$k"
  done

Output:

bar
baz
qux
like image 45
Léa Gris Avatar answered Oct 31 '25 05:10

Léa Gris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!