perl – 使用公共列合并非常大的csv文件

前端之家收集整理的这篇文章主要介绍了perl – 使用公共列合并非常大的csv文件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
例如,我有两个csv文件,
0.csv
100a,a,b,c,c
200a,c
300a,d,c


1.csv

100a,Emma,Thomas
200a,Alex,Jason
400a,Sanjay,Gupta
500a,Nisha,Singh

我希望输出

100a,Jason
300a,0
400a,Singh

我如何在Unix shell脚本或Perl中执行此操作?我知道unix“join”命令,这对小文件很有用.例如,为了获得我的结果,我可以做到

join -t,-a 1 -a 2 -1 1 -2 1 -o 0 1.2 1.3 1.4 1.5 2.2 2.3 -e "0" 0.csv 1.csv

但这对我的目的来说是不可行的,因为我的实际数据文件有超过一百万列(总数据大小为千兆字节),因此我的unix命令也将超过一百万个字符.这可能是最重要的问题,因为低效的代码会很快陷入困境.

另请注意,只要缺少数据,我就需要占位符字符“0”.这使我无法简单地使用它

join -t,-a 1 -a 2 -1 1 -2 1 0.csv 1.csv

也是初学者Perl程序员,所以一些细节真的很受欢迎.我更喜欢解决方案是perl或shell脚本,但实际上任何有效的方法都可以.

解决方法

你也可以用awk做到这一点.

确定两个文件中最宽行的长度并将其保存为max0和max1:

awk -F,'
  ARGIND == 1 && NF > max0 { max0 = NF }
  ARGIND == 2 && NF > max1 { max1 = NF }
  END { print max0,max1 }
' 0.csv 1.csv | read max0 max1

使用此awk脚本进行连接:

foo.awk

BEGIN { 
  max1--
  FS  = OFS = ","
}

ARGIND == 1 {
  A[$1] = $2

  # Copy columns from first file to key
  for(i=3; i<=NF; i++)
    A[$1] = A[$1] FS $i

  # Pad until we have max0 columns
  for( ; i<=max0; i++)
    A[$1] = A[$1] FS "0"
}

ARGIND == 2 {
  # Pad rows which are only in second file
  if(A[$1] == "") {
    A[$1] = 0
    for(i=3; i<=max0; i++)
      A[$1] = A[$1] FS "0"
  }

  # Copy columns from second file to key
  for(i=2; i<=NF; i++)
    A[$1] = A[$1] FS $i

  # Pad until we have max1 columns
  for( ; i<=max1; i++)
    A[$1] = A[$1] FS "0"
}

END { 
  for(key in A) {
    # Pad rows which are only in first file
    split(A[key],fields,",")
    for(i=1; i <= max0+max1-length(fields)-1; i++)
      A[key] = A[key] FS "0"

    # Finally print key and accumulated column values
    print key,A[key]
  }
}

运行:

awk -f foo.awk -v max0=$max0 -v max1=$max1 0.csv 1.csv | sort -n

用-v传入最宽的行值.输出来自哈希并且未排序,因此在显示之前排序-n.

猜你在找的Perl相关文章