user8422062
user8422062

Reputation: 59

expr and if in bash

What's wrong with this code? If I input the number 25, it output failed instead of lol. Am I missing something?

read -p "Enter number : " num
if [ `expr $num > 5` ] 
then 
echo "lol" 
else 
echo "failed" 
fi

Upvotes: 3

Views: 6138

Answers (4)

F. Hauri  - Give Up GitHub
F. Hauri - Give Up GitHub

Reputation: 70822

Same in a short line:

read -p 'Enter a number: ' num
(( num > 5 )) && echo lol || echo fail

could be condensed:

read -p 'Enter a number: ' num;((num>5))&&echo lol||echo fail

This syntaxe will work if first command success!

read -p 'Enter a number: ' num
((num > 5)) && {
      echo lol
      /bin/wrongcommand
      :
 } || echo fail

Could output:

lol
bash: /bin/wrongcommand: No such file or directory

But no fail because of : (is an alias for true) will alway success.

You could of course group command for fail:

read -p 'Enter a number: ' num
((num > 5)) && {
      echo lol
      /bin/wrongcommand
      :
 } || {
      echo fail
      other command
 }

Could be written:

read -p 'Enter a number: ' num;((num>5))&&{ echo lol;/bin/wrongcommand;:;}||{ echo fail;other command;}

You could group commands between and ;} (care about the space after first {!)

Enter a number: 4
fail
bash: other: command not found

Enter a number: 7
lol
bash: /bin/wrongcommand: No such file or directory

Upvotes: 1

tif
tif

Reputation: 1484

@babtistemm's answer gives you the suggested solution but in case you insist on using (the bit oldish) expr for some reason:

read -p "Enter number : " num
if expr "$num" '>' 5 >/dev/null
    then 
        echo "lol" 
    else 
        echo "failed" 
fi

Notes:

  1. You need to quote > so that the shell does not interpret it as redirecting the stdout. You could also use \>.

  2. It is good practice to add double quotes to $num as well, so that expr will interpret it as one expression, thus limiting the chances of a very bad bug or a malicious user hacking your program. (Best would be to do a sanity-check on $num before using it, e.g. checking if it is an integer.)

  3. This solution necessitates calling a new process, expr, which costs a lot more resource from the OS than using the test shell command only.

  4. If you omit the >/dev/null, you will also get a 0 or 1 printed (meaning false or true), the stdout of expr. But independently of that, expr sets its exit status, $? according to the result of the expression, which is tested then by the if. (A side remark: if you try to echo $? after calling expr, it may come at a surprise first that $? = 0 means true/success as exit status, and $? != 0 means false by convention.)

Upvotes: 4

glenn jackman
glenn jackman

Reputation: 246847

you can use an arithmetic expression in bash:

if (( num > 5 )); then ...

In the manual, see https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs

Upvotes: 3

Baptiste Mille-Mathias
Baptiste Mille-Mathias

Reputation: 2169

The code

if [ `expr $num > 5` ] 

actually does not do want you think. It will run expr $num > 5, so evaluate parameter and redirect the out to a file named 5 ("put 25 in a file named 5") and if will evaluate the return code of the previous expression.

If the code if meant to check evaluate if a number is bigger than 5, replace

if [ `expr $num > 5` ] 

with

[ "$num" -gt 5 ]

-gt stands for greater than

Upvotes: 4

Related Questions