I just discovered a weird behavior when indexing into bash arrays with unset elements. I make an array with these three elements:

$ arry[3]=a
$ arry[4]=b
$ arry[5]=c

The array appears to be right:

$ echo ${#arry[@]}
3
$ echo ${!arry[@]}
3 4 5

But if I try to get the first three values in the array, I get a for all of them:

$ echo ${arry[@]:0:1}
a
$ echo ${arry[@]:1:1}
a
$ echo ${arry[@]:2:1}
a

I have to use the actual keys to get the elements I set:

$ echo ${arry[@]:3:1}
a
$ echo ${arry[@]:4:1}
b
$ echo ${arry[@]:5:1}
c

It looks like with substring expansion "offset" means the actual array index, and if unset, Bash just keep scrolling until it finds a set element.

Acknowledging that, is there any straight forward way to get the nth value of an indexed array with some unset element?

share|improve this question
    
What is the output of declare -p arry ? – user79743 Mar 9 '16 at 20:42
    
Here is the output @BinaryZebra declare -a arry='([3]="a" [4]="b" [5]="c")' – Claudio Mar 10 '16 at 21:12
    
That clearly means that the only set values are at index 3, 4 and 5, Therefore, you do need to use those index in ${arry[@]:5:1}. – user79743 Mar 11 '16 at 1:08

is there any straight forward way to get the nth value of an indexed array with some unset element?

Not without a temporary array I think:

a=([3]=2 [1]=12 [12]=4 [23]=5)

a_indices=("${!a[@]}")

third_element=${a[${a_indices[2]}]}

or

a_normalized=("${a[@]}")
third_element=${a_normalized[2]}

That's a ksh heritage. ksh and bash are the only shells that I know where arrays are sparse (or in other words are associative arrays with keys limited to positive integers and numerically sorted on their keys).

The arrays of all other shells that I know (zsh, yash, fish, csh, tcsh, rc, es...) are normal arrays (and with indices starting at 1 like one (at least I) would expect, not 0).

share|improve this answer

According to the Parameter Expansion in Bash

the :x returns the elements from that index to the end.

the :x:y returns y elements from the first extraction.

It has to be views one after the other.

ar[2]=a
ar[3]=b
ar[5]=y
ar[6]=z

echo ${ar[@]:0}
# a b z y

echo ${ar[@]:0:3}
# a b z

echo ${ar[@]:4}
# y z
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.