1

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?

  • 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
1

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).

0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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