Search code examples
phpbashshelldiffcomm

Shell - diff between files and parameters in each line


I am looking for advance two file compare shell/bash/php. Let say i have such files:

file1

.run file=test_script.sql rev=1.1
.run file=test_sql.sql rev=1.1
.run file=test_drop.sql rev=1.2

file2

.run file=test_drop.sql rev=1.2
.run file=test_grant.sql rev=1.1
.run file=test_script.sql rev=1.2

get the difference between those files (ignoring line order) that is

.run file=test_grant.sql rev=1.1 #(because new line wasn't in file1 at all)
.run file=test_script.sql rev=1.2 #(because rev changed from rev=1.1 to rev=1.2)

but that is not all, i want to check if there was same (.run file=name) in the old file and if it was then get it's (rev=number). So that the final output will look like this:

file3:

 test_grant.sql 1.1 1.1
 test_script.sql 1.1 1.2

so far: fgrep -x -v -f file1 file2

gets

.run file=test_grant.sql rev=1.1
.run file=test_script.sql rev=1.2

Solution

  • This awk script should do what you want:

    awk 'NR==FNR {
        map[$2]=$3
        next;
    }
    
    !map[$2] || (map[$2] != $3) {
        sub3=substr($3, index($3,"=")+1)
        subm2=substr(map[$2], index(map[$2],"=")+1)
        print substr($2, index($2,"=")+1), subm2?subm2:sub3, sub3
    }' file1 file2
    

    While looking at the first file (NR==FNR) store the rev field in the map array under the file key.

    While looking at the second file (the second block) if the file field in this line isn't in the map array or the current rev field doesn't match the matching rev field then print the current line.

    To handle lines that were removed you would want to add {delete map[$2]} after the second block and then add END {for (rev in map) {print "Missing: .run "map[rev]" "rev}} to the end.