How to use IF loop in unix for multiple conditions - shell

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

Related

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 use multiple condition in if statement in bash?

Actually I am a new bash learner. I can use one condition in bash command. But how to use multiple condition in bash? I can use if statement like this:
read a
if [ $a = "y" ] ; then
echo "YES"
elif [ $a = "Y" ] ; then
echo "YES"
else
echo "NO"
fi
I am finding something like this:
read a b c
if [ $a -eq $b and $b -eq $c ] ; then
echo "EQUILATERAL"
elif [ $a -eq $b or $b -eq $c ] ; then
echo "ISOSCELES"
else
echo "SCALENE"
fi
I just want to know, what to use instead of and and or?
Use && for and (|| for or)
read a b c
if [ "$a" == "$b" ] && [ "$b" == "$c" ] ; then
echo "EQUILATERAL"
elif [ "$a" == "$b" ] || [ "$b" == "$c" ] ; then
echo "ISOSCELES"
else
echo "SCALENE"
fi
Use && and || to have multiple conditions. Additionally, change the square brackets to parentheses. Additionally change the -eq to == since you're comparing numbers and not strings. This works:
#!/bin/bash
read a b c
if (( $a == $b )) && (( $b == $c )); then
echo "EQUILATERAL"
elif (( $a == $b )) || (( $b == $c )) ; then
echo "ISOSCELES"
else
echo "SCALENE"
fi
In addition to the prior answers, the correct way to use compound expression in a single [ or test (they are the same) clause is to use -a (for and) and -o (for or).
(e.g. testing if both file1 and file2 are readable):
if [ -r "$file1" -a -r "$file2 ]
then
# do something with the files
fi
Using test itself:
if test -r "$file1" -a -r "$file2
then
# do something with the files
fi
The portable way of doing this inside test brackets is to use -a and -o. Beware however that -eq is a numeric comparison, so you need to make sure your variables are numeric before comparing them. Something like this:
#! /bin/sh
read a b c
expr "$a" : '[0-9][0-9]*$' \& "$b" : '[0-9][0-9]*$' \& "$c" : '[0-9][0-9]*$' >/dev/null || exit
if [ $a -eq $b -a $b -eq $c ] ; then
echo "EQUILATERAL"
elif [ $a -eq $b -o $b -eq $c ] ; then
echo "ISOSCELES"
else
echo "SCALENE"
fi

[: too many arguments with Binary Conditional Operators

I am trying to write a script but it is giving the above error
if [ [ [ "$1" != "abc" ] && [ "$1" != "def" ] ] || [ [ "$2" != "1" ] && [ "$2" != "0" ] ] ];
then
echo "Hello World"
fi
Be careful with && and ||. You can simplify it to this in BASH:
if [[ "$1" != "abc" && "$1" != "def" ]] || [[ "$2" != "1" && "$2" != "0" ]];
then
echo "Hello World"
fi

Why does not bash short-circuit work in this case?

Suppose I am writing the following in a bash script:
if [ -z $a ] || [ -z $b ] ; then
usage
fi
It works but I would like to write it with short-circuiting as follows:
[ -z $a ] || [ -z $b ] || usage
Unfortunately it does not work. What am I missing ?
You want to execute usage in case either 1st or 2nd condition are accomplished. For that, you can do:
[ -z $a ] || [ -z $b ] && usage
Test:
$ [ -z "$a" ] || [ -z "$b" ] && echo "yes"
yes
$ b="a"
$ [ -z "$a" ] || [ -z "$b" ] && echo "yes"
yes
$ a="a"
$ [ -z "$a" ] || [ -z "$b" ] && echo "yes"
$
You could make use of the following form:
[[ expression ]]
and say:
[[ -z "$a" || -z "$b" ]] && usage
This would execute usage if either a or b is empty.
Always quote your variables. Saying
[ -z $a ]
if the variable a is set to foo bar would return an error:
bash: [: foo: binary operator expected

Consolidate multiple if statements in Ksh

How can I consolidate the following if statements into a single line?
if [ $# -eq 4 ]
then
if [ "$4" = "PREV" ]
then
print "yes"
fi
fi
if [ $# -eq 3 ]
then
if [ "$3" = "PREV" ]
then
print "yes"
fi
fi
I am using ksh.
Why does this give an error?
if [ [ $# -eq 4 ] && [ "$4" = "PREV" ] ]
then
print "yes"
fi
Error:
0403-012 A test command parameter is not valid.
Try this:
if [[ $# -eq 4 && "$4" == "PREV" ]]
then
print "yes"
fi
You can also try putting them all together like this:
if [[ $# -eq 4 && "$4" == "PREV" || $# -eq 3 && "$3" == "PREV" ]]
then
print "yes"
fi
Do you just want to check if the last argument is "PREV"? If so, you can also do something like this:
for last; do true; done
if [ "$last" == "PREV" ]
then
print "yes"
fi
'[' is not a grouping token in sh. You can do:
if [ expr ] && [ expr ]; then ...
or
if cmd && cmd; then ...
or
if { cmd && cmd; }; then ...
You can also use parentheses, but the semantics is slightly different as the tests will run in a subshell.
if ( cmd && cmd; ); then ...
Also, note that "if cmd1; then cmd2; fi" is exactly the same as "cmd1 && cmd2", so you could write:
test $# = 4 && test $4 = PREV && echo yes
but if your intention is to check that the last argument is the string PREV, you might consider:
eval test \$$# = PREV && echo yes
Try this :
if [ $# -eq 4 ] && [ "$4" = "PREV" ]
then
print "yes"
fi

Resources