if [ 0 ] returns true. why?

2019-07-20 17:33发布

I'm now learning shell-script. Anyway, I run the below program.

#!/bin/bash
sudo rmmod my_driver
make clean
make
sudo insmod my_driver.ko   // return value is 0
var=$?
if [ $var ];
then
        echo " $var, not done!!"
else
        echo " $var, done!!"
fi

The output is,

...
make[1]: Leaving directory `/usr/src/kernels/2.6.32-431.11.2.el6.x86_64'
0, not done!!

In C language(I believe in any language), if if condition returns false it'll execute else block.

I tried below conditions too, but I faced same problem

if [ "$var" ]
if [ "$var" -eq "0" ]
if [ $var -eq 0 ]
if [ $? ]

Why it is not executing else block? How can I execute else block for if [ 0 ]?

6条回答
乱世女痞
2楼-- · 2019-07-20 17:55

Passing any string to the test command, i.e. [, would succeed. So

if [ 0 ]

is equivalent to

if [ 1 ]

or

if [ foobar ]

You could make use of the arithmetic context instead, and say:

if ((var)); then 

or, using the test command as:

if [ $var -eq 0 ]; then
查看更多
唯我独甜
3楼-- · 2019-07-20 17:57

I suggest you run man test. if does nothing but check the return command of the subsequent command, and [ is an alias of test.

Looking at the man page for test you'll find that if the expression you feed it is just a single string it defaults to testing if the string is of non-zero length.

If you want to test for the test for the numeric value of zero, the you must use [ $? -eq 0 ]

It's also worth noting that bash is not C, especially in that a return code of zero is construed as true and non-zero values are false.

查看更多
祖国的老花朵
4楼-- · 2019-07-20 18:04

If you want it to execute the else block if 0, then you have to set it so the condition is anything but 0.

As variables in bash are considered a string, using arithmetic operators (-ne, -gt, -eq) etc, will make it interperet it as a number.

In C you would have to set this as an int/bool for it to use equate to false when 0.

if [[ $var -ne 0 ]];then
    echo " $var, not done!!"
else
    echo " $var, done!!"
fi
查看更多
ら.Afraid
5楼-- · 2019-07-20 18:15

please try [[ test statement,

atleast following will work:

if [[ "$var" -eq "0" ]]
if [[ $var -eq 0 ]]

Why other would not work, well thats because

anything like :

if [ $? ] or if [ "$var" ]

is considered as true in bash

For difference between the [ and [[

查看更多
三岁会撩人
6楼-- · 2019-07-20 18:18

Try this,

[[ $var -ne 0 ]] && echo "$var, not done!!" || echo "$var, done!!"
查看更多
看我几分像从前
7楼-- · 2019-07-20 18:20

In C language(I believe in any language) : there's your problem.

I find it easier to consider that if does not test for true or false but for success or failure. That makes it easier to reconcile the effect of zero, since zero is defined as success.

In Bash, true and : are built-ins (not constants or literals) and both give success.

If you use the test command [ ], (or even [[ ]]) then values resolve to strings:

echo "hello"
if [ $? ]
then
    echo "True"
else
    echo "False"
fi

Gives True.

However, if you use the arithmetic test (( )), then zero is "false":

echo "hello"
if (( $? ))
then
    echo "True"
else
    echo "False"
fi

Gives False

If you think about it, that is the same behaviour as C, where '0' (a const char) will give true but 0 (an int) will give false. That's why if you want a binary zero char in C you use '\0'.

A language where zero (string or numeric) acts as true is Ruby (only nil and false are not true).

查看更多
登录 后发表回答