0

I have two files $A and $B

$A contains (the operator varies, it could be =, > or !=) Basically I have the awk command working as it should I just want to add the line from $A where it failed

number1 = 460
number2 = 12
number3 > 5
number4 > 20
number5 != 39
number6 != 0

$B contains

number1 453
number2 12
number3 7
number4 19
number5 39
number6 4

I have an awk command that compares two files and tells me if the numbers don't match

output=`awk '
   {
       getline buf <f2;
       split( buf, a, " " );

       if( $1 == a[1]  && $2 == ">" && $3+0 > a[2]+0 )
           printf( "%s\n", buf );
       else if( $1 == a[1]  && $2 == "!=" && $3+0 == a[2]+0 )
           printf( "%s\n", buf );
       else if( $1 == a[1]  && $2 == "=" && $3+0 != a[2]+0 )
           printf( "%s\n", buf );

   }
' f2="$B" $A`

echo "$output"
number1 453
number4 19
number5 39

I am trying to get this output:

echo "$output"
This is the line that failed: number1 = 460 #coming from $A
This is the correct number: number1 453 #coming from $B

This is the line that failed: number4 > 20 #coming from $A
This is the correct number: number4 19 #coming from $B

This is the line that failed: number5 != 39 #coming from $A
This is the correct number: number5 39 #coming from $B
TheNewGuy
  • 559
  • 1
  • 10
  • 27
  • 3
    awk is a separate programming language, not part of bash. And bash has a printf but it's completely separate from awk's printf. There's a lot that could be done to make this clearer. – Charles Duffy Apr 07 '21 at 16:21
  • @CharlesDuffy thanks I'll edit the title – TheNewGuy Apr 07 '21 at 16:21
  • BTW, `echo $output` is itself inherently buggy (of particular note it'll eat your newlines and print all your output on the same line, even when you've gotten your code fixed to the point where awk is writing two separate lines of output); _always_ `echo "$output"` instead -- see [I just assigned a variable, but `echo $variable` prints something different!](https://stackoverflow.com/questions/29378566/i-just-assigned-a-variable-but-echo-variable-shows-something-else) – Charles Duffy Apr 07 '21 at 16:22
  • @CharlesDuffy agreed. I fixed it – TheNewGuy Apr 07 '21 at 16:23
  • And `awk` can easily do that in single command without any `bash` directive – anubhava Apr 07 '21 at 16:25
  • 1
    What do you mean by the last line "Note that the operators might change to > or < so its important that the output comes from the file"? It sounds like your files may contain `>` or `<` etc. instead of `=`. But your input and output do not cover those cases. What if `$A` has `number1 > 100` and `$B` has `number1 > 150`? What would be the output? Or does `$B` has `=` only? If so, you need to mention that. – j1-lee Apr 07 '21 at 18:28
  • @j1-lee Thanks for your input. I edited the question with more examples of operators. Hopefully its makes it better to understand – TheNewGuy Apr 08 '21 at 13:38
  • If you're ever considering using `getline` in future, by the way, then make sure to read http://awk.freeshell.org/AllAboutGetline to understand the very few cases where using `getline` is appropriate and how to code it correctly to avoid the various associated issues. – Ed Morton Apr 08 '21 at 14:21

2 Answers2

1
$ cat tst.awk
NR==FNR {
    map[$1] = $2+0
    next
}
$1 in map {
    succ = 0
    if (    ( ($2 == "=" ) && (map[$1] == $3) ) \
         || ( ($2 == "!=") && (map[$1] != $3) ) \
         || ( ($2 == ">" ) && (map[$1] >  $3) ) \
         || ( ($2 == ">=") && (map[$1] >= $3) ) \
         || ( ($2 == "<" ) && (map[$1] <  $3) ) \
         || ( ($2 == "<=") && (map[$1] <= $3) ) \
       ) {
        succ = 1
    }
    if ( !succ ) {
        printf "This is the line that failed: %s #coming from %s\n", $0, FILENAME
        printf "This is the correct number: %s %s #coming from %s\n", $1, map[$1], ARGV[1]
        print ""
    }
}

$ awk -f tst.awk B A
This is the line that failed: number1 = 460 #coming from A
This is the correct number: number1 453 #coming from B

This is the line that failed: number4 > 20 #coming from A
This is the correct number: number4 19 #coming from B

This is the line that failed: number5 != 39 #coming from A
This is the correct number: number5 39 #coming from B
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • 1
    this works great. I was able to fit this inside my bash script. Thanks for your help – TheNewGuy Apr 09 '21 at 14:23
  • instead of $2 == "=" how can I call anything between 2 commas instead of $2 column – TheNewGuy Apr 15 '21 at 17:46
  • Sorry, I don't know what that means (I can imagine several things it **might** mean) and [chameleon questions](https://meta.stackexchange.com/questions/43478/exit-strategies-for-chameleon-questions) are strongly discouraged anyway so please just ask a new followup question. – Ed Morton Apr 15 '21 at 18:24
0

As I prefer to use sed over awk, there is something:

diff -y file1 file2 |
    sed 's/^\(.*\) = *\([0-9]\+\)[ \o11]\+|[ \o11]\+\1/\1 :: \2 !/p;d'
number1 :: 460 ! = 453

You could arrange:

diff -y file? |
    sed 's/^\(.*\) = *\([0-9]\+\)[ \o11]\+|[ \o11]\+\1 = *\([0-9]\+\)/This is the line that failed: \1 = \2 # coming from file1\nThis is the correct number: \1 = \3 # comming from file2/p;d'
This is the line that failed: number1 = 460 # coming from file1
This is the correct number: number1 = 453 # comming from file2
techno
  • 525
  • 3
  • 13
  • Thank you for the sed option however in my case I will have different operators. file1 might have != while file 2 might have >. You can see the criteria in the awk command – TheNewGuy Apr 07 '21 at 18:11