Reputation: 87
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.
Upvotes: 4
Views: 1812
Reputation: 8416
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.
Upvotes: 3
Reputation: 19625
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
Upvotes: 1