Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

How following if statement works in bash script?

Posted on 2011-10-09
17
Medium Priority
?
305 Views
Last Modified: 2013-12-26
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!
0
Comment
Question by:beer9
  • 7
  • 5
  • 4
  • +1
17 Comments
 
LVL 48

Expert Comment

by:Tintin
ID: 36939418
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
0
 

Author Comment

by:beer9
ID: 36939465
"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?
0
 
LVL 31

Expert Comment

by:farzanj
ID: 36939540
Why don't you try something like

if (( grep -c sh 1.txt  > 0 )); then echo found; else echo not found; fi
0
Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

 
LVL 48

Expert Comment

by:Tintin
ID: 36940281
"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.
0
 
LVL 48

Expert Comment

by:Tintin
ID: 36940285
I'm a little confused as to what the issue is.

Your code is correct and your results are correct.
0
 
LVL 31

Expert Comment

by:farzanj
ID: 36941502
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.

0
 
LVL 31

Assisted Solution

by:farzanj
farzanj earned 664 total points
ID: 36941518
if grep -q my  db.pl; then echo good; fi

Actually, exit status is evaluated differently and Unix knows about it.  Exit status of 0 is for true unlike other boolean logic and that is exactly how it is and should be evaluated.
0
 

Author Comment

by:beer9
ID: 36941625
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)
0
 

Author Comment

by:beer9
ID: 36941638
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

0
 
LVL 48

Accepted Solution

by:
Tintin earned 668 total points
ID: 36941808
OK, I can see where your confusion is now.

In an if test, if the entire test evaluates to status 0, then it is true otherwise false.

When you do

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

Open in new window


This is the equivalent of

if [[ '' ]] ; then echo good; else echo bad; fi

Open in new window


because the grep statement is producing no output.

[[ '' ]]  evaluates to false, ie: status 1

You can see this if you do

[[ '' ]] ; echo $?

Open in new window


Same deal with (( ))

However, if you do

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

Open in new window


The if test is using the exit status of grep and not the test itself.

Make sense now?
0
 
LVL 31

Expert Comment

by:farzanj
ID: 36941853
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
0
 

Author Comment

by:beer9
ID: 36941868
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?
0
 
LVL 31

Expert Comment

by:farzanj
ID: 36941871
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
0
 
LVL 31

Expert Comment

by:farzanj
ID: 36941887
Let me be even more specific.  If there is any output for standard output (No standard error), it is true.
No output means false
0
 
LVL 31

Expert Comment

by:farzanj
ID: 36941900
Another thing: Even output of zero is true.  So, it sees output vs. no output.
0
 
LVL 48

Expert Comment

by:Tintin
ID: 36944381
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).
0
 
LVL 4

Assisted Solution

by:Anacreo
Anacreo earned 668 total points
ID: 36945362
Wow this thread is totally derailed and awkward.


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

The return value is what's being processed (not stdout)...  0 is true, anything else is false.  

Return values work in that no news is good news, so a good run is 0.  Remember you're asking it what was the ERROR LEVEL?  Absences of ERROR is No error.

[ ] (alias of test)
(( ))
test

All return 0 for true and 1 for not-true as their error level.

So the real answer is ERROR LEVELS work in the opposite of boolean logic.  And the if statement in the shell scripts, is based on this logic, so the if statement itself is reversed so that a 0 exit level is a success and non 0 is false.

-Anacreo
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Recently, an awarded photographer, Selina De Maeyer (http://www.selinademaeyer.com/), completed a photo shoot of a beautiful event (http://www.sintjacobantwerpen.be/verslag-en-fotoreportage-van-de-sacramentsprocessie-door-antwerpen#thumbnails) in An…
Utilizing an array to gracefully append to a list of EmailAddresses
Learn several ways to interact with files and get file information from the bash shell. ls lists the contents of a directory: Using the -a flag displays hidden files: Using the -l flag formats the output in a long list: The file command gives us mor…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…
Suggested Courses

580 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question