Difference between if with or statement and elif in BASH - bash

I'm just curious about the difference between the following:
if [[ "${foo}" == 'bar' || "${foo}" == 'bar1' ]]; then
echo "Action"
fi
and:
if [ "${foo}" == 'bar' ]; then
echo "Action"
elif [ "${foo}" == 'bar1' ]; then
echo "Same action as above"
fi
Are there any differences? Speed? Preferability for code readability? ..etc?
Thanks

A more direct (and still POSIX-compliant) version of your first statement is
if [ "${foo}" = 'bar' ] || [ "${foo}" = 'bar1' ]; then
echo "Action"
fi
The second one is just unnecessarily verbose.
There is virtually no difference between the two in bash, as [ is a built-in command.

Related

When/how do I decide when to use brackets in tests

I'm having a tough time wrapping my soggy little brain around the various usages of [ ], quoted vars and -eq vs ==.
What is the difference between these statements? Is it as simple as one is more posix compliant than the other or is there a functional difference I should worry about?
[ ! -z "$var" ] && echo "Not empty" || echo "Empty"
[[ ! -z "$var" ]] && echo "Not empty" || echo "Empty"
and what about:
if "$report" == "1"; then blah; fi
vs
if [ "$report" == "1" ]; then blah; fi
vs
[ "$report" -eq 1 ]; then blah
I get that [ is a test function in the shell but I don't understand when I need to start with if or when that isn't necessary.

Complicated if-then-else statement

So, I simplified this code. Every time it runs, else or $msg4 is always executed. How do I change it so it only does else if the $nick part doesn't match?
if [ "$who" = "$nick1" ]
then echo $msg1
fi
if [ "$who" = "$nick2" ]
then echo $msg2
fi
if [ "$who" = "$nick3" ]
then echo $msg3
else $msg4
fi
Here you can read how Bash if statements work: https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html#Conditional-Constructs
There you can see there is an elif which you should use to chain multiple if - else things together so that the final else is only executed if none of the if statements match. Result:
if [ "$who" = "$nick1" ]
then
echo $msg1
elif [ "$who" = "$nick2" ]
then
echo $msg2
elif [ "$who" = "$nick3" ]
then
echo $msg3
else
echo $msg4
fi
You can also write the then on the same line as if if you add a ; before then:
if [ "$who" = "$nick1" ]; then
echo $msg1
elif [ "$who" = "$nick2" ]; then
echo $msg2
elif [ "$who" = "$nick3" ]; then
echo $msg3
else
echo $msg4
fi
This is often easier to read.
Use case .. esac
case "$who" in
"$nick1") echo "$msg1";;
"$nick2") echo "$msg2";;
"$nick3") echo "$msg3";;
*) echo "$msg4";;
esac

How to do character comparison in bash scripts?

Here is my code
#! /bin/bash
read var
if [ $var="Y" -o $var="y" ]
then
echo "YES"
else
echo "NO"
fi
I want to print YES if the user presses y or Y, otherwise I want to print NO. Why doesn't this code work?
Basically, your Condition is wrong. Quote your variables and leave spaces between operators (like shellter wrote). So it should look like:
#! /bin/bash
read var
if [ "$var" = "Y" ] || [ "$var" = "y" ]
then
echo "YES"
else
echo "NO"
fi
Edit: for POSIX ccompatibility
Replaced == with = - see comments
Replaced -o syntax with || syntax - see comments
With Bash, you can also use regular expression in your test with the =~ operator:
read var
[[ "$var" =~ [Yy] ]] && echo "YES" || echo "NO"
Or as Benjamin W. mentionned, simply use character range with the == operator:
read var
[[ "$var" == [Yy] ]] && echo "YES" || echo "NO"
There is minor syntax error in your code.
Correction : There should be a white space between operators and variables
read var
if [ $var = "Y" -o $var = "y" ]
then
echo "YES"
else
echo "NO"
fi
Try the above bash script.
Hope it would work fine.
Happy Coding!
If all you require is a upper/lowercase comparison, use the ,, operator on the variable being compared ( note the ${var,,} ):
#!/bin/bash
read var
if [ ${var,,} = "y" ]
then
echo "YES"
else
echo "NO"
fi
or more succinctly:
#!/bin/bash
read var
[ ${var,,} = 'y' ] && echo 'YES' || echo 'NO'
or the way I might actually do it:
#!/bin/bash
read var
[[ "${var,,}" == 'y' ]] && echo 'YES' || echo 'NO'
Below is the code that I tried.
#! /bin/bash
read -p "Are you Sure?(Y/N) " answer
if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
echo "Do your stuff."
else
echo "Do your other stuff"
fi
Add whitespace around '=' and your code will run fine.
#! /bin/bash
read var
if [ $var = "Y" -o $var = "y" ]
then
echo "YES"
else
echo "NO"
fi
Try this code.
#! /bin/bash
read var
echo -e "YES\nNO\n" | grep -i $var

How to use IF loop in unix for multiple conditions

I need a logic to implement the following logic in unix
if ( $a !="xyz" || $d !="abc" ) && ( $b= $c))
then
echo "YES WORKING"
fi
I tried below code not working
if [ [ [ $a != "xyz" ] -o [ $d != "abc" ] ] -a [ "$b" = "$c" ] ]
then
echo "YES WORKING"
fi
getting error as
:[ :] unexpected operator/operand
You can do something like this:
[ $a != "xyz" -o $d != "abc" ] && [ "$b" = "$c" ] && echo "YES WORKING"
Your logic should work easy in shells supporting [[ ]]:
if [[ ($a != "xyz" || $d != "abc") && $b = "$c" ]]; then
echo "YES WORKING"
fi
Although there's a way for those that doesn't:
if ([ ! "$a" = "xyz" ] || [ ! "$d" = "abc" ]) && [ "$b" = "$c" ]; then
echo "YES WORKING"
fi
But that's still inefficient since you'd be summoning subshells, so use { } but the syntax is a little ugly:
if { [ ! "$a" = "xyz" ] || [ ! "$d" = "abc" ]; } && [ "$b" = "$c" ]; then
echo "YES WORKING"
fi

bash : Illegal number

When I run this bash script :
if [ [$EUID -ne 0] ]; then
echo "This script must be run as root" 1>&2
exit 1
else
printf " whathever "
exit 0
fi
I have this error :
./myScript: 15: [: Illegal number: [
Do you see any problem ?
You have syntax error in your if condition, use this if condition:
if [ "$EUID" -ne 0 ];
OR using [[ and ]]
if [[ "$EUID" -ne 0 ]];
You have syntax error in your if condition, use this if condition:
if [ "$EUID" -ne 0 ];
OR using [[ and ]]
if [[ "$EUID" -ne 0 ]];
If you use the KSH88+/Bash 3+ internal instruction [[, it's not necessary to use doubles quotes around the variables operands :
[ ~/test]$ [[ $var2 = "string with spaces" ]] && echo "OK" || echo "KO"
OK
Instead of the external command test or his fork [ :
[ ~/test]$ [ $var2 = "string with spaces" ] && echo "OK" || echo "KO"
bash: [: too many arguments
KO
[ ~/test]$ [ "$var2" = "string with spaces" ] && echo "OK" || echo "KO"
OK
Of course, you also have to choose the operators according to the type of operands :
[ ~/test]$ var1="01"
[ ~/test]$ [ "$var1" = "1" ] && echo "OK" || echo "KO"
KO
[ ~/test]$ [ "$var1" -eq "1" ] && echo "OK" || echo "KO"
OK
two suggestions apart from what everyone else has pointed out already.
rather than doing else [bunch of code because we are root] fi, just replace the else with fi. once you've tested for the failure condition you are concerned about and taken appropriate action, no need to continue to be within the body of the conditional.
$EUID is a bashism, if you would like to make this portable to shells such as ksh, replacing it with:
if [ $(id -u) -ne 0 ]; then echo "ur not root bro"; exit 1; fi
would be a good way to do it.
using
sudo bash shell_script.sh
instead of
sudo sh shell_script.sh
solved in my case.

Resources