Home > Software design >  How to structure a compound conditional with several tests (at least 1 of which is regex)
How to structure a compound conditional with several tests (at least 1 of which is regex)

Time:04-05

I searched for this but haven't found an answer to this particular situation. I'm familiar with file tests in shells and with using the [[ ]] syntax to perform regex matching.

Is there a way to combine these two operations in a compound conditional that doesn't require multiple nested ifs?

So far I've tried the following (...and other much crazier variations):

if  [   -e ~/.profile   -a   $0 =~ bash         ]; then echo yes ; fi
if  [   -e ~/.profile   -a ( $0 =~ bash )       ]; then echo yes ; fi
if  [   -e ~/.profile   -a [ $0 =~ bash ]       ]; then echo yes ; fi
if [[   -e ~/.profile   -a   $0 =~ bash        ]]; then echo yes ; fi
if [[ ( -e ~/.profile ) -a ( $0 =~ bash )      ]]; then echo yes ; fi

if [ -e ~/.profile -a           $0 =~ bash      ]; then echo yes; fi
if [ -e ~/.profile -a $( [      $0 =~ bash ] )  ]; then echo yes; fi
if [ -e ~/.profile -a   [[      $0 =~ bash ]]   ]; then echo yes; fi
if [ -e ~/.profile -a $([[      $0 =~ bash ]])  ]; then echo yes; fi

CodePudding user response:

-a is treated as an AND when using single brackets, eg:

$ [ 3 -gt 1 -a 2 -lt 3 ] && echo 'true'
true

For double brackets you want to use &&, eg:

$ [[ 3 -gt 1 && 2 -lt 3 ]] && echo 'true'
true

Alternatively you can && two separate tests regardless of whether you're using single or double brackets, eg:

$ [ 3 -gt 1 ] && [ 2 -lt 3 ] && echo 'true'
true

$ [[ 3 -gt 1 ]] && [[ 2 -lt 3 ]] && echo 'true'
true

$ [ 3 -gt 1 ] && [[ 2 -lt 3 ]] && echo 'true'
true

NOTE: same rules apply for -o vs || (aka OR)

CodePudding user response:

Apparently, when you want to represent a LOGICAL AND between these two statements, you must use && instead of -a (which the shell interprets as "does this file exist" file test). Also, for the regex to work, the statement must be within [[ ]].

if [[ -e ~/.profile && $0 =~ bash ]]; then echo yes ; fi

  • Related