CristinaHP
CristinaHP

Reputation: 1

If statement 3 conditions Bash

I want to do an if statement with three conditions that have to be satisfied at the same time. I am using Ubuntu Bash for Windows and the values $c1, $c2 and $c3 are non-integer (decimal negative numbers).

if [ (( $(echo "$c1 < 0" | bc -l) )) ]  && [ (( $(echo "$c2 < 0" | bc -l) )) ] && [ (( $(echo "$c3 < 0" | bc -l) )) ];
    then
      >&2 echo -e "   ++ Constraints OK"

else
      >&2 echo -e "   ++ Constraints WRONG"

fi

However, I get the following syntax error in the if line: syntax error near unexpected token `('

If I just put one condition:

if (( $(echo "$c1 < 0" | bc -l) )); 

it works, but when I add the three of them as AND (&&), I get the error. Can anyone help me?

Upvotes: 0

Views: 10391

Answers (2)

Gil Hamilton
Gil Hamilton

Reputation: 12357

First, pass the relational AND operators into bc to get rid of some punctuation (also only invokes bc once):

if (( $(echo "$c1 < 0 && $c2 < 0 && $c3 < 0" | bc -l) == 1 ))
then
    >&2 echo -e "   ++ Constraints OK"
else
    >&2 echo -e "   ++ Constraints WRONG"
fi

Although if it were me, I would create a shell function returning a "true" exit status if bc evaluates the result of an expression to non-zero. Then you can hide most of the ugly punctuation in one place separated from your main logic:

function bc_true() {
    (( $(echo "$@" | bc -l) != 0 ))
}

And write a (IMO) cleaner shell expression:

if bc_true "$c1 < 0 && $c2 < 0 && $c3 < 0"
then
    ...

Upvotes: 0

Charles Duffy
Charles Duffy

Reputation: 295914

Considerably more efficient (assuming you know your values are numbers, and only need to check whether they're all negative) would be:

if [[ $c1 = -* ]] && [[ $c2 = -* ]] && [[ $c3 = -* ]]; then
      >&2 echo "   ++ Constraints OK"
else
      >&2 echo "   ++ Constraints WRONG"
fi

If you want to be more specific about the permissible formats (f/e, allowing leading spaces), a regex is another option, which similarly can be implemented more efficiently than spawning a series of subshells invoking bc:

nnum_re='^[[:space:]]*-([[:digit:]]*[.][[:digit:]]+|[[:digit:]]+)$'
if [[ $c1 =~ $nnum_re ]] && [[ $c2 =~ $nnum_re ]] && [[ $c3 =~ $nnum_re ]]; then
      >&2 echo "   ++ Constraints OK"
else
      >&2 echo "   ++ Constraints WRONG"
fi

Upvotes: 1

Related Questions