0

I have two text files 1.txt and 2.txt that contain two tab separated columns. The first column of both files consists of tokenized text. In both files, the first column is the same. The word order matters. The second column consists of tags. In the first file, the tokenization is complete but imprecise. In the second file, it is incomplete but precise.

1.txt:

I          3
was        5
there      6
yesterday  6
.          0

2.txt:

I          3
was        
there      12
yesterday  
.          0

I want to merge these two files (while maintaining the order of the lines) so that there is a tag on each line and so the more precise (i.e. the tags from file 2.txt) are preferred as follows:

I          3
was        5
there      12
yesterday  6
.          0

I've tried using join, but it can display only both of the tags or just the tags from one file:

$ join 1.txt 2.txt 
I          3 3
was        5 
there      6 12
yesterday  6 
.          0 0
$ join -1 1 -2 1 -o 1.1,2.2 1.txt 2.txt
I          3
was        
there      12
yesterday  
.          0

This answer using awk seems close but doesn't deliver the desired result. I'd also prefer using coreutils.

3
  • ... so the logic you'd want to modify the linked answer is something like $2 = ($2 == "") ? a[$1] : $2 ? Dec 31, 2022 at 14:33
  • @steeldriver Yes! awk 'NR==FNR{a[$1]=$2; next} {$2 = ($2 == "") ? a[$1] : $2} 1' 1.txt 2.txt seems to work both for this testing input and my real files.
    – winety
    Dec 31, 2022 at 15:13
  • Regarding I'd also prefer using coreutils - even better than GNU coreutils, awk is a mandatory POSIX tool so it exists on all Unix installations, not just ones that have GNU coreutils.
    – Ed Morton
    Jan 2, 2023 at 0:49

2 Answers 2

0

Using awk :

awk 'NR==FNR{if (NF==2) a[$1]=$2; next}
     {print $1,($1 in a ? a[$1] : $2)}' 2.txt 1.txt
  • NR==FNR if the number record is equal to the file number record (if you are in the first file)
  • a[$1]=$2 Store into an array the second field using the first field as the key
  • $1 in a ? a[$1] : $2 if $1 is a key in a print a[$1] else print $2
0
0

Here's another option:

join 1.txt 2.txt | awk -e '{if($NF == "") print $1, $(NF - 1); else print $1, $NF}' | column -t

which gives:

I          3
was        5
there      12
yesterday  6
.          0

the | column -t is optional, but just formats it in nice columns.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .