0

The following code prints "Odd" no matter what number I put in, why doesn't it print "Even" when given an even number as an argument?

if [[ 'echo "$1%2" | bc' =~ 0 ]]
then
        echo "Even"
else
        echo "Odd"
fi
smeepy
  • 3

3 Answers3

3

You are matching the regular expression 0 to the string echo "$1%2" | bc. The string does not contain a 0, so the else branch is taken.

To test whether $1 is odd or even, use an arithmetic test instead:

if (( $1 % 2 == 0 )); then
    echo even
else
    echo odd
fi

The (( ... )) bit is an arithmetic evaluation. It will evaluate the expression inside and its value will be the result of that expression. The if statement can then act on the result.

To use bc as you intended to do:

if [ "$( printf '%s %% 2\n' "$1" | bc )" -eq 0 ]; then
    echo even
else
    echo odd
fi

That is, use a command substitution (the $(...) bit) to insert the result of running the command within it, then compare that to zero using -eq (for an arithmetic comparison).

If using printf feels funny, then use

if [ "$( echo "$1 % 2" | bc )" -eq 0 ]; then
    echo even
else
    echo odd
fi

but see "Why is printf better than echo?".

Kusalananda
  • 333,661
0

The single quotes prevent the $1 from being replaced. Experiment with quoting parts of that statement to get the results you want.

0

Even though you can use a simpler and independent solution (only using bash, cause this one depends on bc too), your try was almost correct; simply change ' for ` (a backtick):

if [[ `echo "$1%2" | bc` =~ 0 ]]
then
        echo "Even"
else
        echo "Odd"
fi 

what you tried:

'echo "$1%2" | bc'

what you meant:

`echo "$1%2" | bc`

On the other hand, you are using =~:

An additional binary operator, ‘=~’, is available, with the same precedence as ‘==’ and ‘!=’. When it is used, the string to the right of the operator is considered a POSIX extended regular expression and matched accordingly (as in regex3)).

Probably, this is not what you want, but, in this particular case, will work just fine: n%2 no matter what natural number n is, always will give you 0 or 1. 1 (when the number is odd) doesn't match the regex 0, so, you are safe... but, beware: this could be wrong in another case: the regex 0 will match 0, but 10,707,2.71828182845905, or anything with a 0 too. In a case like this, you want to use =, instead of =~.

Also, notice that $(...) is preferred over the backticks.