Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash / zsh script behaviour difference

Tags:

bash

zsh

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?

like image 590
user2141650 Avatar asked Nov 28 '25 12:11

user2141650


1 Answers

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
like image 127
Etan Reisner Avatar answered Nov 30 '25 05:11

Etan Reisner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!