I'm trying to be smart but it doesn't work. Can anybody help me to do this a bit simpler?
if [[ "${DATUM}" == "${today}" && "${STUNDE}" == "${HH24}" ]] || [[ "${DATUM}" == "${today}" && "${STUNDE}" == "20" ]] ||
[[ "${DATUM}" == "${today}" && "${STUNDE}" == "" && "20" == "${HH24}" ]]; then
Is there a way to combine it?
Your code can be translated to:
(C1 and C2) or (C1 and C3) or (C1 and C4 and C5)
Applying boolean arithmetics you can simplify it as:
C1 and (C2 or C3 or (C4 and C5))
This said, you can add a nested if statement to, first, check the C1 condition and, second, check the other conditions. It does not simplify the code a lot but here it is:
if [ "${DATUM}" = "${today}" ]; then
if [ "${STUNDE}" = "${HH24}" ] || [ "${STUNDE}" = "20" ] || { [ "${STUNDE}" = "" ] && [ "${HH24}" = "20" ]; }; then
# Insert the code to execute when the conditions are satisfied
fi
fi
As others have noted, your boolean expression can be simplified applying the law of distributivity of conjunction (⋀, *, AND) over disjunction (⋁, +, OR):
(a ⋀ b) ⋁ (a ⋀ c) = a ⋀ (b ⋁ c)
But to simplify it further, note you can, in bash, use && and || inside the (bash-specific) [[ .. ]] command:
[[ $a == 1 && $b == 2 ]]
Also, when using [[ .. ]] compound command (over POSIX [ .. ]) you don't have to quote variables. And to test for null-strings, you can use the shorter -z $var form over $var == "".
All this together yields:
if [[ $DATUM == $today ]] && [[ $STUNDE == $HH24 || $STUNDE == 20 || -z $STUNDE && $HH24 == 20 ]]; then
# ...
fi
To further simplify it, we would need to have more details on your application logic, possible values, etc.
Related
I have this code:
fruit=apple
flag=0
[[ $fruit = "apple" && ((flag == 0)) ]] && echo "1"
[[ $fruit = "apple" && (($flag == 0)) ]] && echo "2"
[[ $fruit = "apple" && ((! flag)) ]] && echo "3"
[[ $fruit = "apple" && ((! $flag)) ]] && echo "4"
All of them are expected to echo something. However, only the second statement works properly:
[[ $fruit = "apple" && (($flag == 0)) ]] && echo "2"
Why is this? Won't arithmetic expressions work properly inside [[ ]]?
The == works the same as = - it is a string comparision.
The ( ) inside [[ ]] is used to nest expressions. Ex. [[ a = a && (b = b || c = d) ]]
A non empty string is true. So [[ some_string ]] or [[ "some other string" ]] returns true. [[ "" ]] or [[ '' ]] returns false.
The ! is negation.
[[ $fruit = "apple" && ((flag == 0)) ]]
First the expansion of $fruit happens. So it becomes: [[ "apple" = "apple" && ( ( "flag" == "0" ) ) ]]. The ( ) are just braces, this is not arithemtic expansion. The string "apple" is equal to "apple", but the string "flag" is not equal to string "0", so it always returns with false.
[[ $fruit = "apple" && (($flag == 0)) ]]
Because $flag is expanded, the [[ sees: [[ "apple" = "apple" && ((0 == 0)) ]]. So the comparision happens to work, however == is doing string comparision.
[[ $fruit = "apple" && ((! flag)) ]]
The flag is a nonempty string, so it evaulates to true. The ! flag evaulates to false.
[[ $fruit = "apple" && ((! $flag)) ]]
First $flag is expanded to 0. As 0 is a nonempty string, it evaluates to true. The ! 0 evaluates to false. The ((! 0)) is false, so the whole expression returns nonzero.
Won't arithmetic expressions work properly inside [[ ]]?
No, arithmetic expressions will not work inside [[ ]] the same way [[ echo 1 ]] does not work. The echo 1 ]] are arguments of [[ builtin, not a standalone command. The same way [[ (( 0 )) ]] the (( 0 )) ]] are interpreted as arguments to [[.
((...)) is an arithmetic command (or statement); the arithmetic expresson is $((...)). You want
[[ $fruit = "apple" ]] && ((flag == 0)) && echo 1
# etc.
[[ $fruit = apple && $((flag == 0)) ]] would fail because [[ ... ]] would simply treat the evaluation of the arithmetic expression as a non-empty string (which is always true) rather than a boolean value.
For completeness, you could use a single [[ ... ]] command:
[[ $fruit = apple && flag -eq 0 ]] && echo 1
# etc
i have the following code
elif [ $text2 == 'LANDING' ] && [ "$text4" == 'FAIL' ] || [ "$text4" == '' ]; then
the condition is that text2 should be landing and text4 can either be fail or null.
How to evaluate the above command.
Please help if Im doing any wrong
Thanks in advance
You need to group them explicitly:
elif [ "$text2" = 'LANDING' ] &&
{ [ "$text4" = 'FAIL' ] || [ "$text4" = '' ]; }; then
Your attempt would succeed either of the following two conditions held:
text2 was LANDING and text4 was FAIL
text4 was empty or unset.
Since && and || have the same precedence, you could (perhaps surprisingly) write it without grouping:
elif [ "$text4" = '' ] || [ "$text4" = FAIL ] && [ $text2 == 'LANDING' ]; then
If you are using bash, you can use the [[ ... ]] command instead of [ ... ]. The grouping is required; the operators inside [[ ... ]] do have the precedences you would expect from other languages (that is, a || b && c is a || (b && c), not (a || b) && c).
elif [[ $text2 == 'LANDING' && ( "$text4" == 'FAIL' || "$text4" == '') ]]; then
Not particular recommended, but with bash, you can use extended globbing patterns in [[...]]
elif [[ $text2 == 'LANDING' && $text4 == #(FAIL|) ]]; then
Use curly braces or parentheses to group the || operands together. Parentheses look nicer, but they create a subshell which is inefficient, so curly braces are the way to go even though they're ugly.
elif [ $text2 == 'LANDING' ] && { [ "$text4" == 'FAIL' ] || [ "$text4" == '' ]; }; then
Notice that the curly braces require an extra semicolon.
Alternatively, if you're using bash you could use double square brackets, which allow for the slightly prettier:
elif [[ $text2 == 'LANDING' && ("$text4" == 'FAIL' || "$text4" == '') ]]; then
I have a shellscript that tells me missing ] in the line
if [ $status != "2" && $status != "3" && `echo "$temp1 > $upperLimit" | bc` = "1" ]
and also missing ] in the line
if [ $status = "2" && `cat motionsensordate` \> `date +%s` ]
Why is that?
The single [ doesn't support logical operators inside the brackets. You have to use them outside
if [ "$status" != 2 ] && [ "$status" != 3 ] ...
Use double quotes for variables in single brackets to prevent unary operator expected error when the variable is empty.
Or, switch to double brackets:
if [[ $status != 2 && $status != 3 ... ]]
Also, status different to 2 and 3 can be expressed by a pattern:
if [[ $status != [23] && ... ]]
And if you would like to (in addition to the answers here) group together conditions:
if [[ ( COND1 || COND2 ) && COND3 ]]
then
echo "$cmd"
break
fi
This question already has answers here:
Why does non-equality check of one variable against many values always return true?
(3 answers)
Closed 8 years ago.
#!/bin/bash
(...)
if [ "$1" == "" ] || [ "$2" == "" ] || [ "$3" == "" ] || [ "$4" == "" ] ; then # WORKS!
echo "Erro #1: Nao inseriu todos os argumentos necessarios! Tente novamente!"
echo "Ajuda #1: Lembre-se, ep1.sh [diretoria] [modo] [informação] <nome_do_ficheiro>"
elif [[ "$2" != "contar" || "$2" != "hist" ]] ; then **# THE PROBLEM!!!**
echo "Erro #2: O segundo argumento está incorrecto! Tente novamente!"
echo "Ajuda #2: Use contar ou hist."
elif [[ "$3" != "palavras" || "$3" != "bytes" ]] ; then # CAN'T TEST BECAUSE OF FIRST ELIF
echo "Erro #3: O terceiro argumento está incorrecto! Tente novamente!"
echo "Ajuda #3: Use palavras ou bytes."
(...)
fi
So, my problem is in the first elif, when the elif is False, the program should not enter in the elif, but enters.
I do not see what could be the problem.
Can anyone help me?
Use && not ||.
elif [[ "$2" != "contar" && "$2" != "hist" ]] ; then
The reason for switching the operator is De Morgan's law. If you negate
if [[ $a == "foo" || $b == "bar" || $c == "baz" ]]
you get
# negated
if ! [[ $a == "foo" || $b == "bar" || $c == "baz" ]]
De Morgan's law says you can distribute the ! by switching all the =='s to !='s and changing || to &&.
# `!` distributed per De Morgan's law
if [[ $a != "foo" && $b != "bar" && $c != "baz" ]]
The problem I am experience involves multiple IF statements. For some reason the script is validating against the code below even with the settings as follows:
SSLSite is Defined as N
SSLOnly is Undefined
Subdomain is Defined as N
if ([[ $SSLSite == y* || $SSLSite == Y* ]] && [[ $SSLOnly == n* || $SSLOnly == N* ]] && [[ $Subdomain == n* ]] || [[ $Subdomain == N* ]])
Any ideas?
Thanks.
Your long if condition can be shortened to:
[[ "$SSLSite" == [yY]* && "$SSLOnly" == [nN]* && "$Subdomain" == [nN]* ]]
To directly answer your question, the problem is your last condition: [[ $Subdomain == n* ]] || [[ $Subdomain == N* ]].
The || here is not grouped inside the [[ .. ]] like in the other clauses. This gives you
(A || B) && (C || D) && (E) || (F)
where you wanted
(A || B) && (C || D) && (E || F)
The former expression is true if F alone is true, which is why it's validating when Subdomain=N
You can solve it by making the last clause [[ $Subdomain == n* || $Subdomain == N* ]] instead, but clearly anubhava's syntax is better.