Andres Aguado
Andres Aguado

Reputation: 63

[[]] if condition with variable logical operator

I have the following text in a file1:

aaa common-criteria policy POLICY1

  min-length 8 

  max-length 16

  numeric-count 1

  upper-case 3

  lower-case 2

  char-changes 4

!

and the following text in a file2:

aaa common-criteria policy POLICY2

  min-length 1

  max-length 127 

  char-changes 4

!

I would like to check all values in both files are correct, based on the threshold in my policies. I have created two arrays with thresholds in order to compare each value with those from each file

declare -a COM=("min-length" "max-length" "upper-case" "lower-case" "numeric-count")
declare -a OPE=("-ge" "-le" "-ge" "-ge" "-ge")
declare -a VAL=("8" "16" "1" "1" "1")

And I've created loop to check each value from file against value in VAL(i)

for ((i=0; i<${#COM[@]}; i++)); do
    THRESHOLD=$(grep ${COM[$i]} FILE | awk -F " " '{print $2}') --> to get value VAL(i) for each comand COM(i)

if [[ $THRESHOLD -ge "${VAL[$i]}" ]]; then echo "OK"; else echo "KO"; fi

done

Next step should be to change "-ge" to OPE(i) in if condition, to allow each command be analyzed in the right way, as "max-length" value should be less than threshold. If I change "-ge" to ${OPE[$i]} if [[ "$THRESHOLD" "${OPE[$i]}" "${VAL[$i]}" ]] the process fails with this message:

conditional binary operator expected syntax error near `${OPE[$i]}'

Do you know if "if" condition has this flexibility syntax?

Upvotes: 1

Views: 118

Answers (2)

Dudi Boy
Dudi Boy

Reputation: 4865

It is possible to use test command with arguments passed as variables:

test command example:

v1=1; op=" -eq "; v2=1
if test "$v1 $op $v2"; then echo true; else echo false; fi
true

v1=1; op=" -eq "; v2=0
if test "$v1 $op $v2"; then echo true; else echo false; fi
false

Suggesting to use associative arrays in gawk script, which is standard awk in Linux machine:

script.awk

function boolExprTest(expr) { # function to test bool exression provided as input string
  split(expr, exprToken); # split input string into tokens
  # return boolean expression result for each 2nd token
  if (exprToken[2] == ">=") return exprToken[1] >= exprToken[3];
  if (exprToken[2] == "<=") return exprToken[1] <= exprToken[3];
  if (exprToken[2] == ">")  return exprToken[1] > exprToken[3];
  if (exprToken[2] == "<")  return exprToken[1] <  exprToken[3];
  if (exprToken[2] == "==")  return exprToken[1] ==  exprToken[3];
}

BEGINFILE { # at the beging of each input file read
  # define boolean expression templates using associative arry boolExpr[]
  boolExpr["min-length"] = " >= 8";
  boolExpr["max-length"] = " <= 16";
  boolExpr["upper-case"] = " >= 1";
  boolExpr["lower-case"] = " >= 1";
  boolExpr["numeric-count"] = " >= 1";
  # define current file's results using associative arry currResults[]
  currResults["min-length"] = "undefined";
  currResults["max-length"] = "undefined";
  currResults["upper-case"] = "undefined";
  currResults["lower-case"] = "undefined";
  currResults["numeric-count"] = "undefined";
  # print file seperator
  print "---------------+---------------+-------------";
}

# for each line in current file 
$1 in boolExpr { # if 1st field is a member in boolExpr[]
  currResults[$1] = "fail"; # default result is fail in currResults[]
  if (boolExprTest($2 boolExpr[$1])) { # used function boolExprTest () to test "$2 boolExpr[$1]"
    currResults[$1] = "pass"; # set pass result in currResults[]
  }
}

ENDFILE { # at the end of each input file read
  for (argument in currResults) { # iterate results
    #fromat print the results
    printf("%-15s|%-15s|%s\n", FILENAME, argument, currResults[argument]);
  }
}

output:

$ awk -f script.awk input.*.txt
---------------+---------------+-------------
input.1.txt    |numeric-count  |pass
input.1.txt    |max-length     |pass
input.1.txt    |lower-case     |pass
input.1.txt    |min-length     |pass
input.1.txt    |upper-case     |pass
---------------+---------------+-------------
input.2.txt    |numeric-count  |undefined
input.2.txt    |max-length     |fail
input.2.txt    |lower-case     |undefined
input.2.txt    |min-length     |fail
input.2.txt    |upper-case     |undefined

Upvotes: 1

choroba
choroba

Reputation: 241768

[[ ... ]] is parsed in a special way before variables are expanded, therefore it's not possible (that's also why you don't need to alwyas double quote the variables in [[ ... ]]). But you can use the old [ ... ] which follows the normal parsing rules.

op==
[ x "$op" x ]  # ok

Upvotes: 1

Related Questions