user2141650
user2141650

Reputation: 2857

bash / zsh script behaviour difference

I have a simple script:

is_prime () {
    local factors
    factors=( $( factor "$1" | cut -d ':' -f 2 ) )
    [ ${#factors} -le 1 ]
}

starting () {
    for i in $(seq 10 99); do
        if is_prime "$i" ; then echo "$i" ; fi
    done
}


starting

If I run it with /bin/zsh, it prints all the primes between 10 and 99, as I would expect. If I run it with /bin/bash, however, it does the exact opposite: it prints all non-prime values in that range! I understand zshs behaviour, but why does bash do what it does? Is the behaviour of test different in some relevant way?

Upvotes: 3

Views: 111

Answers (1)

Etan Reisner
Etan Reisner

Reputation: 80931

Apparently in zsh this ${#factors} expansion on an array gets you the length of the array. It doesn't do that in bash. In bash that gets you the length of the first element of the array.

Compare these outputs:

$ zsh -c 'foo=(a b c); echo $foo'
a b c
$ bash -c 'foo=(a b c); echo $foo'
a
$ zsh -c 'foo=(a b c); echo ${#foo}'
3
$ bash -c 'foo=(a b c); echo ${#foo}'
1

So that's why your script is going wrong for bash. To get the value you expected there you need to use ${#factors[@]} (which also works in zsh).

$ zsh -c 'foo=(a b c); echo ${#foo[@]}'
3
$ bash -c 'foo=(a b c); echo ${#foo[@]}'
3

Upvotes: 3

Related Questions