用awk合并两个文件

paw*_*ana 9 command-line awk text-processing

File1.txt

item1   carA
item2   carB
item3   carC
item4   platD
item5   carE
Run Code Online (Sandbox Code Playgroud)

File2.txt

carA  platA
carB  platB
carC  platC
carE  platE
Run Code Online (Sandbox Code Playgroud)

想要的输出:

item1   platA
item2   platB
item3   platC
item4   platD
item5   platE
Run Code Online (Sandbox Code Playgroud)

我该怎么做?

Yar*_*ron 11

以下答案基于SO 中类似问答,并进行了一些相关修改:

$ awk 'FNR==NR {dict[$1]=$2; next} {$2=($2 in dict) ? dict[$2] : $2}1' file2.txt file1.txt 
item1 platA
item2 platB
item3 platC
item4 platD
item5 platE
Run Code Online (Sandbox Code Playgroud)

这个想法是创建一个带有索引的哈希映射,并将其用作字典。

对于您在评论中提出的第二个问题(如果第二列file1.txt将是第六列,应该更改什么):

如果输入文件类似于file1b.txt

item1 A5 B C D carA
item2 A4 1 2 3 carB
item3 A3 2 3 4 carC
item4 A2 4 5 6 platD
item5 A1 7 8 9 carE
Run Code Online (Sandbox Code Playgroud)

以下命令将执行此操作:

$ awk 'FNR==NR {dict[$1]=$2; next} {$2=($6 in dict) ? dict[$6] : $6;$3="";$4="";$5="";$6=""}1' file2.txt file1b.txt 
item1 platA    
item2 platB    
item3 platC    
item4 platD    
item5 platE    
Run Code Online (Sandbox Code Playgroud)


JoL*_*JoL 6

我知道你说过awk,但有一个join用于此目的的命令......

{
  join -o 1.1,2.2 -1 2 -2 1 <(sort -k 2 File1.txt) <(sort -k 1 File2.txt)     
  join -v 1 -o 1.1,1.2 -1 2 -2 1 <(sort -k 2 File1.txt) <(sort -k 1 File2.txt) 
} | sort -k 1
Run Code Online (Sandbox Code Playgroud)

join如果不是这一行,第一个命令就足够了:

item4   platD
Run Code Online (Sandbox Code Playgroud)

该命令基本上说:基于第一个文件的第二列(-1 2)和第二个文件的第一列(-2 1)连接,并输出第一个文件的第一列和第二个文件的第二列(-o 1.1,2.2)。那只显示配对的线。第二个 join 命令说的几乎相同,但它表示显示第一个文件中无法配对的行 ( -v 1) ,并输出第一个文件的第一列和第一个文件的第二列 ( -o 1.1,1.2)。然后我们对两者的输出进行排序。sort -k 1表示基于第一列sort -k 2排序,表示基于第二列排序。在将文件传递给join.

现在,我写了两次排序,因为如果可以的话,我不喜欢在我的目录中乱扔文件。但是,就像 David Foerster 所说的那样,根据文件的大小,您可能希望对文件进行排序并首先保存它们,而不必等待对每个文件进行两次排序。为了给出大小的概念,以下是在我的计算机上对 100 万行和 1000 万行进行排序所需的时间:

$ ruby -e '(1..1000000).each {|i| puts "item#{i}   plat#{i}"}' | shuf > 1million.txt 
$ ruby -e '(1..10000000).each {|i| puts "item#{i}   plat#{i}"}' | shuf > 10million.txt 
$ head 10million.txt 
item530284   plat530284
item7946579   plat7946579
item1521735   plat1521735
item9762844   plat9762844
item2289811   plat2289811
item6878181   plat6878181
item7957075   plat7957075
item2527811   plat2527811
item5940907   plat5940907
item3289494   plat3289494
$ TIMEFORMAT=%E
$ time sort 1million.txt >/dev/null
1.547
$ time sort 10million.txt >/dev/null
19.187
Run Code Online (Sandbox Code Playgroud)

100 万行需要 1.5 秒,1000 万行需要 19 秒。