File1.txt
item1 carA
item2 carB
item3 carC
item4 platD
item5 carE
File2.txt
carA platA
carB platB
carC platC
carE platE
想要的输出:
item1 platA
item2 platB
item3 platC
item4 platD
item5 platE
我该怎么做?
答案1
以下答案基于类似的问答并进行了一些相关修改:
$ 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
这个想法是创建一个带有索引的哈希图,并将其用作字典。
对于你在评论中提出的第二个问题(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
以下命令可以完成此操作:
$ 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
答案2
我知道你说过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
join
如果没有这一行,第一个命令就足够了:
item4 platD
该命令基本上是说:根据第一个文件的第二列(-1 2
)和第二个文件的第一列(-2 1
)进行连接,并输出第一个文件的第一列和第二个文件的第二列(-o 1.1,2.2
)。这只显示配对的行。第二个连接命令几乎说的是同样的事情,但它表示显示第一个文件中无法配对的行(-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
也就是说,100 万行需要 1.5 秒,1000 万行则需要 19 秒。