例如,我有两个csv文件,
0.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