将 csv 与多个字段连接起来而不扰乱顺序

将 csv 与多个字段连接起来而不扰乱顺序

我有 2 个 csv 文件。第一个文件很大(> 400 个字段,许多行> 1 百万),需要通过匹配的连接附加另一个字段。

我想加入一个领域 $170

我努力了

gawk 'BEGIN {OFS=FS=","} NR==FNR{b[$1]=$2; next} 
$170 in b {print $0,b[$170]}
' b a

据介绍,这工作正常,但当文件大小增加时就会遇到困难 为什么这个 awk 命令不执行完整的外连接?(参见@cuonglm 的回答)

我还没有对此进行测试,但想知道随着文件大小增加的“最佳”方法。

@cuonglm 建议使用join,但这会重新排列列以将连接的字段放在第一位。我无法轻松地使用参数
为命令编写长输出格式,因为这会很长:join-o

join -1 170 -2 1 -o1.1 1.2 1.3 1.4......1.300.... file1 file2

有没有办法join更轻松地做到这一点?

或者我应该坚持使用gawk,因为文件大小问题(例如,文件 a 和 b 中最多 5 百万行,两者都有大约 500 列)?

答案1

我进行了全面的呆呆测试。我制作了一个 500 万行 x 500 列 (20 GB) 的 CSV,以及一个 500 万行 x 2 列的辅助文件。关键字段是唯一的(我有 500 万素数),位于大文件的第 170 列和副文件的第 1 列中。这两个文件都包含独立随机顺序的密钥。所有其他字段包含从大约 14000 个单词中随机选择的内容(摘自手册页)。

awk 脚本运行了近 20 分钟,整个过程使用了大约 0.8 GB 内存。这是在 4 GB 笔记本电脑和 5400 rpm 硬盘上。该日志显示时间和文件大小以及列数。

Paul--) time ./datMerge

real    18m31.740s
user    10m21.632s
sys 1m48.316s
Paul--) wc -lc *max*
    5061456 20045559105 FileA.max.csv
    5061456    85634275 FileB.max.csv
    5061456 20085640276 FileC.max.csv
   15184368 40216833656 total
Paul--) for f in F*max*; do
> awk '-F,' '{ printf ("%8d %s\n", NF, FILENAME); }' "${f}"
> done | uniq -c
5061456      500 FileA.max.csv
5061456        2 FileB.max.csv
5061456      501 FileC.max.csv
Paul--) ls -l F*max*
-rw-r--r-- 1 paul paul 20045559105 Feb  8 19:49 FileA.max.csv
-rw-r--r-- 1 paul paul    85634275 Feb  8 19:49 FileB.max.csv
-rw-r--r-- 1 paul paul 20085640276 Feb  8 20:24 FileC.max.csv
Paul--) 

我制作了一个迷你版本的文件来展示它的作用,六行六列,密钥位于第 4 列中。

Paul--) head F*mini*
==> FileA.mini.csv <==
rather,complies,finite,99999847,AM,Or
elapsed,plied,nearperfect,99999989,pr,WinChip
phiopt,reflects,bottom,99999959,128N,careful
fpackstructn,realworld,msingleexit,99999931,0xffff,maxmimum
simplified,mpopcntb,FrontCover,99999971,523x,requisite
cede,fdumprtlbtl2,atmega649a,99999941,LC_MESSAGES,errno

==> FileB.mini.csv <==
99999847,symbols
99999931,fdumprtldbr
99999959,ambiguous
99999971,crc
99999989,munsafedma

==> FileC.mini.csv <==
rather,complies,finite,99999847,AM,Or,symbols
elapsed,plied,nearperfect,99999989,pr,WinChip,munsafedma
phiopt,reflects,bottom,99999959,128N,careful,ambiguous
fpackstructn,realworld,msingleexit,99999931,0xffff,maxmimum,fdumprtldbr
simplified,mpopcntb,FrontCover,99999971,523x,requisite,crc
cede,fdumprtlbtl2,atmega649a,99999941,LC_MESSAGES,errno,Default
Paul--) 

这是合并脚本。如果数据创建脚本能提供有用的信息,我可以发布它。

Paul--) cat datMerge
#! /bin/bash
#: datMerge

LC_ALL="C"

function Merge {

    local AWK='''
BEGIN { FS = ","; OFS = ","; K = 170; Null = "Default"; }
NR == FNR { htMap[$1] = $2; next; }
{ printf ("%s%s%s\n", $0, OFS, ($(K) in htMap) ? htMap[$(K)] : Null); }
'''
    awk "${AWK}" "${@}"
}

    Merge "FileB.max.csv" "FileA.max.csv" > "FileC.max.csv"

Paul--) 

相关内容