Link to home
Start Free TrialLog in
Avatar of beer9
beer9Flag for India

asked on

How following if statement works in bash script?

bash-4.1$ if grep -q sh 1.txt; then echo found; else echo not found; fi
found
bash-4.1$ if grep -q she 1.txt; then echo found; else echo not found; fi
not found
bash-4.1$ cat 1.txt
bash

Open in new window


grep would return 0 if there is match and 1 if there is no match. I assume 0 is false but I getting 'found' output. What is happening here. Please help me to understand it. Thanks!
Avatar of Tintin
Tintin

A 0 exit status means success and >0 means not successful.

So when grep successfully matches something, it has an exit status of 0 and when grep doesn't match anything, it has an exit status of 1
Avatar of beer9

ASKER

"if" is using the exit status.. so if grep return 1 ( not found) then that is "true" and it should print "found" but it is printing "not found".

How is it working here?
Why don't you try something like

if (( grep -c sh 1.txt  > 0 )); then echo found; else echo not found; fi
"if" is using the exit status.. so if grep return 1 ( not found) then that is "true"

No.  A non zero status is false if you are using an if test.
I'm a little confused as to what the issue is.

Your code is correct and your results are correct.
Well if you use the operators right, you get what you want
if [[ $(grep sh 1.txt) ]]; then echo found; else echo not found; fi

Within [[ ]], exit status of 0 is true and yes you don't need -q.

SOLUTION
Avatar of farzanj
farzanj
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of beer9

ASKER

Hi farzanj, here are four different ways which is creating more confusion to me.

bash-3.2$ if [[ $(grep -q sh 1.sh) ]] ; then echo good; else echo bad; fi
bad
bash-3.2$ if [[ ! $(grep -q sh 1.sh) ]] ; then echo good; else echo bad; fi
good
bash-3.2$ cat 1.sh
bash

Open in new window


above one if there is match then "if" gets 0 and I am using negate to make it correct. which is fine with me

bash-3.2$ if (( $(grep -q sh 1.sh) )) ; then echo good; else echo bad; fi
bad
bash-3.2$ if ! (( $(grep -q sh 1.sh) )) ; then echo good; else echo bad; fi
good

Open in new window


same as above example

bash-3.2$ if (( 0 )) ; then echo good; else echo bad; fi
bad
bash-3.2$ if (( 1 )) ; then echo good; else echo bad; fi
good

Open in new window


above one is mathematical evaluation and 0 means false and 1 is ture. that is also ok


bash-3.2$ if grep -q sh 1.sh; then echo good; else echo bad; fi
good
bash-3.2$ if ! grep -q sh 1.sh; then echo good; else echo bad; fi
bad

Open in new window


if this one I am failed to understand, if is evaluating 0 as true and 1 as false (grep return 0 if there is match, and return 1 if there is no match)
Avatar of beer9

ASKER

Again, there is one more confusion over using -q of grep. Both are totally opposite

bash-3.2$ if [[ $(grep -q sh 1.sh) ]] ; then echo good; else echo bad; fi
bad
bash-3.2$ if [[ ! $(grep -q sh 1.sh) ]] ; then echo good; else echo bad; fi
good
bash-3.2$ cat 1.sh
bash

Open in new window


bash-3.2$ if [[ $(grep  sh 1.sh) ]] ; then echo good; else echo bad; fi
good
bash-3.2$ if ! [[ $(grep  sh 1.sh) ]] ; then echo good; else echo bad; fi
bad

Open in new window

ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Well, it appears to me that it is not going by exit status at all.  Please disregard my earlier comment.

If it sees any output, anything not zero then it is true.  If there is no output, or output is zero, it will be false.


if [[ $(grep -q sh 1.sh) ]] ; then echo good; else echo bad; fi
bad


if [[ $(grep sh 1.sh) ]] ; then echo good; else echo bad; fi
good

grep -q sh 1.sh      ---- No output
grep sh 1.sh
sh
Avatar of beer9

ASKER

Thanks Tintin for the clarification.

for below

if $(grep -q sh 1.sh)  ; then echo good; else echo bad; fi

Open in new window


the exit status is 0 so "if" should fail and print bad. how we are getting "good" instead?
Accept my apology for earlier comment as I think it was not correct.

It is not going by exit status but the output.  Zero or no output means false otherwise true.

Reason I am saying this is the exit status of both the statements is 0.

> grep -q sh 1.sh
>echo $?
0


>grep sh 1.sh
sh
>echo $?
0
Let me be even more specific.  If there is any output for standard output (No standard error), it is true.
No output means false
Another thing: Even output of zero is true.  So, it sees output vs. no output.
Just remember in *nix, 0 means success and >0 means not success.

Ultimately all the variations of the if tests will evaluate to a status of 0 (true) or 1 (false).
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial