Executing if dynamic conditions in awk

Hi All,

I got struck at the below point where i am unable to get the desired output after forming the dynamic conditions.Below is the design.

  1. We are getting inputs from the shell arguments and storing in a variable like below.
CONDITIONS="1=CT,2=US_10,3=CT_US_10"
  1. After this i am mapping the position of the fields and storing the condition in the variable as below
CON=$1 == "CT" && $4 == US_10 && $60 == CT_US_10
  1. I wish to apply it in the if statement get the desired output as below, however it is not working.
usr/bin/awk -v CONDITION="${CON}" 'BEGIN{FS=","}{ if (CONDITION) {print CONDITION"|"$147"|"$15"|"$16"|"$17"|"$4} } '

Can anyone help us

Hi
the question under item 2. is not entirely clear
can you show the code how you are mapping and storing in the variable?

Hi Moderators,
My sincere apologies.
@nezabudka, Please see the below code

#Shell arguments
#-------------------
sh samplecollector.sh "20200212" "1=CT,2=US_10,3=CT_US_10"

#Inside the script
#----------------------
FILEDATE=$1
CONDITIONS=$2 # Used the values directly in the variable in my post, the condition can be one or many based on user input

/usr/bin/awk -v COND=${CONDITIONS} -F"," 'function strcondition(h,  i,F,v,b,dec) {F=split(h,v,",");for(i=1;i<=F;i++) {split(v,b,"=");dec=(dec != "") ? dec""sprintf(" %s == \"%s\" &&",lookup(b[1]),b[2]) : sprintf("%s == \"%s\" &&",lookup(b[1]),b[2]);} sub(/[ &&\t\r\n]+$/, "", dec);return dec;} function lookup(l,  f,ar){ar[1]="$1";ar[2]="$4";ar[3]="$60";ar[4]="$17";ar[5]="$4";if (l in ar) {return ar[l];}} { if(strcondition(COND));{print COND"|"$147"|"$15"|"$16"|"$17"|"$4}}' Record_${FILEDATE}.dat

And where did you get the CONDITION variable in "awk"?

--- Post updated at 21:59 ---

Is a colon needed here?

maybe

{ if(strcondition(COND))print COND"|"$147"|"$15"|"$16"|"$17"|"$4}
1 Like

A one or two line data sample would be nice.

The if (...); will do nothing.
The print CONDITION will print an empty entity as the variable is not defined.

Your idea / approach will not work per se. You will need to compile your COND in, e.g. have some text tool write a script which then will be executed by awk .

1 Like

You need to assign the return value from the function "strcondition(COND)" to CONDITION

an ex.:

CONDITIONS="1=CT,2=US_10,3=CT_US_10"

CON='$1 == "CT" && $4 == "US_10" && $60 == "CT_US_10"'

awk -v CONDITION="${CON}" -F, '
BEGIN {
c=split(CONDITION, cons, " *&& *");
for (i=1; i<=c; i++) {
split(cons, cs, " *== *");
sub("[$]", "", cs[1]);
gsub("[\"]", "", cs[2]);
conditions[cs[1]]=cs[2];
}
}
{
n=0;
for (i in conditions) if ($(i)==conditions) n++;
if (n==c) print CONDITION"|"$147"|"$15"|"$16"|"$17"|"$4;
}
' file
1 Like
{ if(CONDITION = strcondition(COND)) print CONDITION"|"$147"|"$15"|"$16"|"$17"|"$4 }

Hi,

Before I post i store the condition in a variable as like below(in 2 steps) and after that i merged in the same awk as per above snippet, however the problem statement remains the same where iam unable to execute the if statement with dynamically formed condition.

CON=`echo ""|/usr/bin/awk -v COND=${CONDITIONS} -F"," 'function strcondition(h,  i,F,v,b,dec) {F=split(h,v,",");for(i=1;i<=F;i++) {split(v,b,"=");dec=(dec != "") ? dec""sprintf(" %s == \"%s\" &&",lookup(b[1]),b[2]) : sprintf("%s == \"%s\" &&",lookup(b[1]),b[2]);} sub(/[ &&\t\r\n]+$/, "", dec);return dec;} function lookup(l,  f,ar){ar[1]="$1";ar[2]="$4";ar[3]="$60";ar[4]="$17";ar[5]="$4";if (l in ar) {return ar[l];}} { print(strcondition(COND))}'`

/usr/bin/awk -v CONDITION="${CON}" 'BEGIN{FS=","}{ if (CONDITION) {print CONDITION"|"$147"|"$15"|"$16"|"$17"|"$4} }' Record_${FILEDATE}.dat

--- Post updated at 02:45 PM ---

Hi rdrtx1, It works perfectly. Many thanks for your support.

Hi ,

I have simplified the solution and sharing the final solution for others.

CONDITIONS="1=CT,2=US_10,3=CT_US_10"

awk -v CONDITION="${CONDITIONS}" -F, 'BEGIN { c=split(CONDITION, cons, ","); for (i=1; i<=c; i++) { split(cons, cs, "="); field=lookup(cs[1]); gsub("[\"]", "", cs[2]); conditions[field]=cs[2];}}
function lookup(l,  ar){ar[1]="1";ar[2]="4";ar[3]="60";ar[4]="17";ar[5]="4";if (l in ar) {return ar[l];}}
{
n=0;
for (i in conditions) if ($(i)==conditions) n++;
if (n==c) print CONDITION"|"$147"|"$15"|"$16"|"$17"|"$4;
}
' Record_${FILEDATE}.dat

Then you should consider properly formatting your code, so others can easily read it.

Thanks.

CONDITIONS="1=CT,2=US_10,3=CT_US_10"

awk -v CONDITION="${CONDITIONS}" -F, '
BEGIN { 
	c=split(CONDITION, cons, ",");
	for (i=1; i<=c; i++) { 
		split(cons, cs, "=");
		field=lookup(cs[1]); 
		gsub("[\"]", "", cs[2]); 
		conditions[field]=cs[2];
		}
} 
function lookup(l,  ar){
  ar[1]="1";ar[2]="4";ar[3]="60";ar[4]="17";ar[5]="4";
  if (l in ar) {
    return ar[l];
  }
}
{
n=0;
for (i in conditions) if ($(i)==conditions) n++;
if (n==c) print $0;
}' Record_${FILEDATE}.dat
1 Like

more simple?

CONDITIONS="1=CT,4=US_10,60=CT_US_10"

awk -v CONDITIONS="${CONDITIONS}" -F, '
BEGIN { c=split(CONDITIONS, cn, "[=,]"); }
{n=0;
for (i=1; i<=c; i+=2) if ($cn==cn[i+1]) n+=2;
if (n==c) print $0;
}' file
1 Like

Thats cool rdrtx1. However anxious to see how OR condition works as below are AND conditions.

In our example the below conditions are treated as AND conditions and file got processed.

CONDITIONS="1=CT,2=US_10,3=CT_US_10" 

converted to

CONDITIONS="1=CT,4=US_10,60=CT_US_10"

Can you please throw some light on how to work with AND,OR conditions together if the condition comes dynamically from user input. Below is an example.

CONDITIONS="(1=CT or 2=US_10) and 3=CT_US_10 and 4=" 

You could use sed (or similar) to convert your input syntax to an awk expression eg:

CONDITIONS="(1=CT or 2=US_10) and 3=CT_US_10 and 4="
CONDITIONS=$(echo "$CONDITIONS" |
   sed \
      -e 's/\([1-9][0-9]*\)=/$\1=/g' \
      -e 's/= *\([^() ]*\)\([^ ]*\)/== "\1"\2/g' \
      -e 's/ and / \&\& /g' \
      -e 's/ or / || /g' \
)

if ! awk '{if ('"$CONDITIONS"') { print } }' file
then
   echo "Illegal syntax unable to filter file"
fi
2 Likes