根据列匹配2个大型csv?

时间:2014-04-02 22:52:57

标签: linux perl sed awk

我有2个大型csv如下:

csv1.txt

ID,Name
a0BQ0007OeSDSA,John
a0BQ0013OeBMAU,May
a0BQ0003OeAASA,Marry
a0BQ0032OeBNGG,Peter
....

csv2.txt

ID,Email
a0BQfg343eBMAU,no@email.com
a0BQ0033OeAASA,Mar3ry@email.com
a0BQ0007OeSDSA,Johsdn@email.com
a0BQ0032OeBNGG,Peter@email.com
...

输出:我想匹配csv2到csv1并输出一个具有相同ID

csv3.txt

John,Johsdn@email.com
Peter,Peter@email.com

由于

4 个答案:

答案 0 :(得分:3)

您可以使用join命令,但由于数据文件不是基于ID列的排序顺序,您还必须使用sort命令加上Bash process substitution加上sed命令跳过标题行。

join -t, -o1.2,2.2 <(sed 1d csv1.txt | sort) <(sed 1d csv2.txt | sort)

对于您的给定输入,这会产生您想要的输出。

答案 1 :(得分:3)

这是一个Perl解决方案。它首先从csv2.txt读取电子邮件,然后将它们存储在哈希中以便快速查找。然后读取csv1.txt,并从散列中获取每个名称的电子邮件并使用名称打印。

如果名称在散列中没有条目,则忽略名称。

use strict;
use warnings;

open my $fh, '<', 'csv2.txt' or die $!;

my %emails;
while (<$fh>) {
  chomp;
  my ($id, $email) = split /,/;
  $emails{$id} = $email;
}

open $fh, '<', 'csv1.txt' or die $!;

while (<$fh>) {
  chomp;
  my ($id, $name) = split /,/;
  next unless exists $emails{$id};
  my $email = $emails{$id} or next;
  print "$name,$email\n";
}

<强>输出

Name,Email
John,Johsdn@email.com
Peter,Peter@email.com

答案 2 :(得分:2)

使用awk

awk 'BEGIN{FS=OFS=","}NR==FNR{a[$1]=$2;next}$1 in a{$1=a[$1];print}' csv1.txt csv2.txt
Name,Email
John,Johsdn@email.com
Peter,Peter@email.com

awk 'BEGIN{FS=OFS=","}NR==FNR{a[$1]=$2;next}($1 in a)&&$1=a[$1]' csv1.txt csv2.txt

答案 3 :(得分:1)

纯壳

while IFS=, read -r id1 name
do
   while IFS=, read -r id2 email
   do
      if [ "$id1" =  "$id2" ]; then
         echo "$name,$email"
      fi
   done < csv2.txt
done < csv1.txt

Name,Email
John,Johsdn@email.com
Peter,Peter@email.com