I am new to shell scripting, but doing my best to learn things. Today doing courses there was exercise like this:
#!/usr/bin/bash
a=$1
b=$2
if [[ $a == "A" && $b == "B" ]]
then
echo "Conditions are met"
else
echo "Conditions are not met"
fi
I improved it a little, beacuse of curiosity to this:
#!/bin/sh
a=$1
b=$2
if [[ $a == "A" || $a == "a" && $b == "B" || $b == "b" ]]
then
echo "Conditions are met"
else
echo "Conditions are not met"
fi
And here is funny thing: when you put vaules to script as: ./script b b it shows that conditions are met, but they shouldn't - at least accroding to the first script they shouldn't, the thing I changed is sensitivity for small letters.
Maybe it's written wrong? Have no idea, please advise
You are having a problem with the precedence of operators. In that expression, the AND operator has higher precedence than the OR operator, so the expression in your if statement is evaluated as though you had written:
if [[ $a == "A" || ( $a == "a" && $b == "B" ) || $b == "b" ]]
To get what I think you were trying to do, you want something more like:
#!/bin/sh
a=$1
b=$2
if [[ ( $a == "A" || $a == "a" ) && ( $b == "B" || $b == "b" ) ]]
then
echo "Conditions are met"
else
echo "Conditions are not met"
fi
No. That has the same precedence problem as the code in post #1 in this thread. To do this using only POSIX-defined utilities, one way to do it would be:
#!/bin/ksh
a=$1
b=$2
if { [ "$a" = "A" ] || [ "$a" = "a" ]; } && { [ "$b" = "B" ] || [ "$b" = "b" ]; }
then
echo "Conditions are met."
else
echo "Conditions are not met."
fi
This was written and tested using a Korn shell, but will also work with any other POSIX-conforming shell.
EDIT:
Sorry about the edit but......
Just noticed the semi-colons, can you explain why they are needed?
---------- Post updated at 11:43 AM ---------- Previous update was at 10:09 AM ----------
It seems like this does work too...
#!/usr/local/bin/dash
a=$1
b=$2
if ( [ "$a" = "A" ] || [ "$a" = "a" ] ) && ( [ "$b" = "B" ] || [ "$b" = "b" ] )
then
echo "Conditions are met."
else
echo "Conditions are not met."
fi
Results, OSX 10.7.5, default [bash] terminal but calling 'dash'.
AMIGA:barrywalker~> cd Desktop/Code/Shell
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh a
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh b
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh "" b
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh b ""
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh a ""
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh "" a
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh a a
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh a b
Conditions are met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh b a
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh b b
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh A b
Conditions are met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh A B
Conditions are met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh a B
Conditions are met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh B B
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh B A
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh B b
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh B a
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh A A
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> ./AND_OR.sh b B
Conditions are not met.
AMIGA:barrywalker~/Desktop/Code/Shell> _
if ( [ "$a" = "A" ] || [ "$a" = "a" ] ) && ( [ "$b" = "B" ] || [ "$b" = "b" ] )
executes [ "$a" = "A" ] || [ "$a" = "a" ] in a subshell environment and if it evaluates to true it then evaluates [ "$b" = "B" ] || [ "$b" = "b" ] in a subshell execution environment. In this construct, the parentheses are shell operators.
The command:
if { [ "$a" = "A" ] || [ "$a" = "a" ]; } && { [ "$b" = "B" ] || [ "$b" = "b" ]; }
executes [ "$a" = "A" ] || [ "$a" = "a" ] in the current shell executionl environment and if it evaluates to true it then evaluates [ "$b" = "B" ] || [ "$b" = "b" ] in the current shelll execution environment. In this construct, the braces are shell keywords; not shell operators. The <semicolon>s are shell operators used to delimit the keywords. You could also see this written as:
if { [ "$a" = "A" ] || [ "$a" = "a" ]
} && { [ "$b" = "B" ] || [ "$b" = "b" ]
}
using <newline> instead of <semicolon> to delimit the brace keywords.
I used braces instead of parentheses to avoid creating two subshells.