Shell脚本实现多CSV文件基于双主键列合并的技术求助
多CSV文件按主键合并解决方案
我明白你被这个多CSV文件合并的问题困扰好久了,前两列作为主键合并后续字段的需求其实用awk就能很好解决,先说说为什么你之前用join可能没成功,再给你一个靠谱的脚本方案:
为什么join可能没成功?
join命令默认只处理两个文件,而且要求输入文件按主键排序,另外你的文件分隔符是; (分号加空格),join默认用空白字符分隔,如果你没指定-t';'或者处理空格的问题,就会匹配出错。而且要合并5个以上文件的话,需要多次嵌套join,操作起来非常繁琐,这也是你没成功的大概率原因。
用awk实现多文件合并的脚本
awk可以轻松处理任意数量的CSV文件,并且自动按主键关联内容,完全符合你的需求:
基础版脚本(不保留原文件主键顺序)
创建一个名为merge_csv.awk的文件,内容如下:
BEGIN { # 设置输入输出的分隔符为你的文件格式:分号加空格 FS = OFS = "; " } { # 用前两列拼接成唯一主键 key = $1 OFS $2 # 提取当前行从第三列开始的所有内容,作为当前文件对应主键的值 current_val = "" for (i=3; i<=NF; i++) { current_val = current_val (current_val ? OFS : "") $i } # 关联数组存储主键对应的所有值:首次遇到则初始化,否则追加新值 if (!(key in data)) { data[key] = current_val } else { data[key] = data[key] OFS current_val } } END { # 遍历所有主键,输出合并后的内容 for (key in data) { print key, data[key] } }
保留原文件主键顺序的版本
如果希望合并后的输出顺序和第一个文件中主键出现的顺序一致,可以用下面的版本:
BEGIN { FS = OFS = "; " } { key = $1 OFS $2 current_val = "" for (i=3; i<=NF; i++) { current_val = current_val (current_val ? OFS : "") $i } if (!(key in data)) { data[key] = current_val # 记录主键首次出现的顺序 order[++order_count] = key } else { data[key] = data[key] OFS current_val } } END { # 按记录的顺序输出 for (i=1; i<=order_count; i++) { print order[i], data[order[i]] } }
运行脚本的命令
把所有要合并的CSV文件放在当前目录,然后执行:
awk -f merge_csv.awk *.csv > merged_output.csv
执行后,merged_output.csv就是你想要的合并结果。
测试验证
用你给出的示例文件测试:
File1.csv内容:
1 ; 1.1 ; xyz
1 ; 1.2 ; abc
2 ; 2.1 ; gfaFile2.csv内容:
1 ; 1.1 ; dft
1 ; 1.2 ; asd
2 ; 2.1 ; qwe
运行脚本后,输出文件内容完全符合你的期望:
1 ; 1.1 ; xyz ; dft 1 ; 1.2 ; abc ; asd 2 ; 2.1 ; gfa ; qwe
内容的提问来源于stack exchange,提问作者Teo
相关产品推荐
相关产品推荐

