4

file1:

abc|123|check
def|456|map
ijk|789|globe
lmn|101112|equator

file2:

abc|123|check
def|456|map
ijk|789|equator
lmn|101112|globe

EXPECTED OUTPUT:

ijk|789|equator
lmn|101112|globe

Current awk script:

awk 'BEGIN{OFS=FS="|"} NR==FNR{a[$3]=$3;next}!($3 in a)' file1 file2

This does comparison based on array content. How to compare line by line and printing only that results.

0

3 Answers 3

5

If I understand you correctly, you want to print a line from file2 if the 3rd field is different to the corresponding entry in file1. If so, this should do it:

awk 'BEGIN{FS="|"} NR==FNR{a[$1,$2]=$3;next}(a[$1,$2]!=$3)' file1  file2

Yours wasn't working because you were taking $3 as the key for array a and $3 is not unique (both equator and globe are present in both files).

I agree with @drewbenn that both grep and join are simpler for this particular case, but here's a Perl way of doing the same thing:

perl -laF'\|' -ne '($k{$F[0].",".$F[1]}||=$F[2]) eq $F[2]||print;' file1  file2
2
  • You should use a[$1,$2] in case you get unfortunately similar fields like a|bc|d and ab|c|e Sep 23, 2013 at 13:00
  • @glennjackman good point, answer edited.
    – terdon
    Sep 23, 2013 at 13:16
5

I think you want to use join (or grep -f) instead. But if you must use awk:

echo | awk '{system("join -v 2 file1 file2")}'

which is just an awk front-end to join -v 2 file1 file2. Similarly, of course, you can use grep -v -f file1 file2.

1
  • join is the tool for the job, but your awk solution is cheating.
    – jordanm
    Sep 23, 2013 at 11:20
5

comm is the real tool for this job:

comm -13 file1 file2
ijk|789|equator
lmn|101112|globe

If the input files are not already sorted:

comm -13 <(sort file1) <(sort file2)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.