1

I have 2 files

cat file1.txt
lspol > 8296
....
cat file2.txt
lspol 8297
...

I am trying to get output if the number for column 1 in file2.txt is greater than number in for column 1 in file1.txt

The command below works great

# if column 1 of file1.txt is equal to column 1 of file2.txt and column 3 of file1.txt is greater than column 2 in file2.txt
awk '
   {
       getline buf <f2;
       split( buf, a, " " );
       if( $1 == a[1]  && $3+0 > a[2]+0 )
           printf( "%s\n", buf );
   }
' f2="file2.txt" file1.txt

I am trying to pull the operator from 2nd column in file1.txt but no luck. I have tried many ways and here is one of them

awk '
   {
       getline buf <f2;
       split( buf, a, " " );
       if( $1 == a[1]  && $3+0 $2 a[2]+0 )
           printf( "%s\n", buf );
   }
' f2="file2.txt" file1.txt
tripleee
  • 175,061
  • 34
  • 275
  • 318
TheNewGuy
  • 559
  • 1
  • 10
  • 27
  • 1
    This is an unhappy attempt to mix code and data. You could go all in and have the shell write an Awk script from strings you pick out from the data, or do the safe but tedious thing and map each operand string to a function, like `if((oper=="<") && (a < b)) ... else if ((oper==">") && (a > b)) ...` – tripleee Feb 17 '21 at 20:30

2 Answers2

1

Using unvalidated input is always risky but I THINK this might be what you're trying to do:

$ cat tst.awk
NR==FNR {
    ops[$1] = $2
    vals[$1] = $3
    next
}
{ comparison = sprintf("%d %s %d", $2, ops[$1], vals[$1]) }
system("awk \047BEGIN{exit} END{exit (" comparison ")}\047")

$ awk -f tst.awk file1 file2
lspol 8297

The numeric values at the end of each line are already safe as they're specifically being converted to numbers if they weren't already numbers and you can make the operator safe with:

$ cat tst.awk
NR==FNR {
    if ( $2 ~ /^[!<>=~]{1,2}$/ ) {
        ops[$1]  = $2
        vals[$1] = $3
    }
    else {
        print "Bad operator:", $2 | "cat>&2"
        exit 1
    }
    next
}
{ comparison = sprintf("%d %s %d", $2, ops[$1], vals[$1]) }
system("awk \047BEGIN{exit} END{exit (" comparison ")}\047")

or some other such regexp for whatever comparison operators you want to support.

The above cheats as it's not evaluating the operator within 1 awk command, instead it's using awk to call awk through a subshell to evaluate the expression you want tested. Given that, it will be orders of magnitude slower than hard-coding the comparisons within 1 awk command.

See also https://stackoverflow.com/a/54161251/1745001 for a similar script.

If that's not exactly what you're trying to do then edit your question to clarify your requirements and provide more truly representative sample input/output.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
1

you can build something like this...

$ awk 'NR==FNR{cond[$1]=$2; v[$1]=$3; next}
              {switch(cond[$1])  {
                 case "<": if($2<v[$1]) print; break;
                 case ">": if($2>v[$1]) print; break;
                 case "=": if($2==v[$1]) print; break;
                 default: print "unknown op or missing " $1; break;
              }}' file1 file2

lspol 8297
karakfa
  • 66,216
  • 7
  • 41
  • 56