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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With