如何用批处理脚本(结合gawk)高效去除CSV指定字段重复项
高效筛选CSV中未归档的文件记录(基于name字段)
直接用gawk的哈希表实现O(n+m)复杂度的处理,比嵌套for循环快几个数量级,具体方案如下:
基础版(name字段不含逗号)
gawk -F',' 'NR==FNR {names[$3]=1; next} !($3 in names)' alreadyinarchive.csv copytoarchive.csv > unarchived_files.csv
命令拆解:
-F',':指定CSV的分隔符为逗号NR==FNR:仅在处理第一个输入文件(alreadyinarchive.csv)时触发,把所有归档文件的name字段(第3列)存入哈希表namesnext:读完归档文件的一行后直接跳至下一行,不执行后续逻辑!($3 in names):处理第二个文件(copytoarchive.csv)时,检查当前行的name是否不在归档哈希表里,不在就输出整行- 最后将结果重定向到
unarchived_files.csv
进阶版(name字段含逗号/带引号)
如果你的name字段包含逗号(CSV中会用双引号包裹),用FPAT正确识别带引号的字段:
gawk 'BEGIN {FPAT = "([^,]*)|(\"[^\"]+\")"} NR==FNR {names[$3]=1; next} !($3 in names)' alreadyinarchive.csv copytoarchive.csv > unarchived_files.csv
FPAT的作用是匹配两种字段:要么是不含逗号的纯文本,要么是双引号包裹的任意内容(包括逗号),避免把带逗号的name拆成多个字段。
带表头的处理方式
如果两个CSV第一行是表头,需要保留表头同时跳过表头的处理:
gawk -F',' ' BEGIN {OFS=","} # 处理归档文件:跳过表头,记录name NR==FNR { if (NR>1) names[$3]=1; next } # 处理源文件:先输出表头,再筛选记录 FNR==1 {print; next} !($3 in names) ' alreadyinarchive.csv copytoarchive.csv > unarchived_files.csv
内容的提问来源于stack exchange,提问作者Joshua Howard
相关产品推荐
相关产品推荐

