Enumerating every other array element in loop

0

I have a dynamic array with key-pair values and I’d like to enumerate every other value. In this case, just the names in the array. Since I’m not using bash v4, I have been able to use seq to step through an array using echo.

$ array=(Guido yes Francesca no Balthazar yes)
for x in $(seq 0 2 ${#array[@]});do echo $x;done
0
2
4
6

This returns one more element than pairs I have (due to 0 offset) but I can account for that using simple bash math:

for x in $(seq 0 2 $((${#array[@]}-1)));do echo $x;done
0
2
4

This works just fine. But as soon as I try to pull elements out of $array, I get an error that I cannot explain. I've tried with and without the "math"

$ for x in $(seq 0 2 $((${#array[@]}-1)));do echo ${array[$x]};done
-bash: 0: syntax error: operand expected (error token is "0")

$ for x in $(seq 0 2 ${#array[@]});do echo ${array[$x]};done
-bash: 0: syntax error: operand expected (error token is "0")

How can I get just the names out of this dynamic array?

EDIT: my $BASH_VERSION is 3.2.57(1)-release (Mac OS X 10.10.2)

EDIT #2: I’ve come to the conclusion this is possibly a bug in this version. Since I manage a number of AWS instances, I decided to check them and they all have bash 4.1.2(1). I upgraded my Mac to this version and this now works. Thanks for looking but I'm chalking this up to an anomaly.

SaxDaddy

Posted 2015-03-14T02:21:26.880

Reputation: 3 181

I copied your command and pasted it into my system, and it worked as you wanted (it printed ${array[0]}, ${array[2]}, ${array[4]}, ...). Can you work backwards for the command you've posted to one that works (maybe something that prints every element, either with a loop or set | grep "^array") and post that? – Scott – 2015-03-14T04:36:50.083

Works fine with bash 3.2.39(1)-release. Please add output of echo $BASH_VERSION to your question. – Cyrus – 2015-03-14T06:36:28.893

Folks, since I'm on a Mac, I decided to check the AWS instances I manage. All of them have bash 4.1.2(1). So I upgraded my Mac to that version and this now works. I suspect it's a bug in that particular version but I'm moving on. Thanks both for your help. – SaxDaddy – 2015-03-15T06:09:43.227

I suggest that you take your resolution to your program (bug in old version), which you added to your question and tacked on as comments, and post it as an answer. Then accept it. (You might need to wait a few hours before you can accept your own answer.) This will make it more readily obviously that this question is resolved and doesn't need any further attention. This is preferred over putting "Resolved:" into the title. (Also, you get 2 reputation points for accepting you own answer.) – Scott – 2015-03-17T13:50:53.037

Answers

2

If want to loop over alternate elements of the array, this one should work on bash 3.2:

while IFS= read -d '' -r name; do
  # do something with "$name"
done < <(printf %s%.0s\\0 "${array[@]}")

You could do similar things with xargs -0 if that was more convenient.

If none of your names includes a colon (for example), you could extract the names into a new array like this:

IFS=: read -a names -r < <(printf %s%.0s: "${array[@]}")

(Unfortunately you can't set the field separator to NUL.)

All of these are dependent on the fact that printf repeats its format string as often as is necessary to use all its arguments (Posix behaviour, so it should work on any bash version, or with the non-builtin printf). The occasionally useful format %.0s uses an argument and prints at most 0 characters from it, which is to say drops it into the bitbucket.

rici

Posted 2015-03-14T02:21:26.880

Reputation: 3 493

(I don't understand why your for loop doesn't work either, but I have no bash 3 to test it with. It must be some weirdness in the evaluation of the array subscript; is the error in the OP copy-and-pasted directly from the console? – rici – 2015-03-15T05:39:52.110

I don't know either but since I'm on a Mac and managing AWS systems, I checked and all of them have bash 4.1.2(1). I used homebrew to update my Mac to that version and this now works. I suspect it's a bug in that particular version but I'm moving on. Thanks for your help. – SaxDaddy – 2015-03-15T06:07:13.820