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
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
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?".
The single quotes prevent the $1 from being replaced. Experiment with quoting parts of that statement to get the results you want.
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.
test
(or[[
) gets'string' =~ 0
as an argument - whether it contains %, $ and | or not! – trs Jun 25 '19 at 23:15