我有 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--)