如何用Bash/AWK保留CSV文件中首字段唯一的行?
按CSV首字段去重(仅保留首字段唯一的行)的Bash/AWK实现方案
要解决这个需求——只保留CSV文件中第一个字段完全唯一的行(也就是去掉所有首字段重复出现的行,不管是第一次还是后续出现的),用AWK是最简洁高效的方案,还能轻松保留原文件的行顺序。
核心方案(保留原行顺序)
下面这个AWK脚本可以完美实现你的需求,输出结果会严格遵循原文件中首次出现的行顺序:
awk -F, '{ # 首次遇到该首字段时,记录顺序、保存行内容并计数 if (!($1 in count)) { count[$1] = 1 line_order[++order_idx] = $1 line_content[$1] = $0 } # 再次遇到时,增加计数并删除已保存的行(因为该字段重复了) else { count[$1]++ delete line_content[$1] } } # 遍历顺序数组,输出仅保留的唯一行 END { for (i=1; i<=order_idx; i++) { current_key = line_order[i] if (current_key in line_content) { print line_content[current_key] } } }' your_input.csv
脚本逻辑拆解
-F,:指定CSV的字段分隔符为逗号,确保正确识别第一个字段。count[$1]:统计每个首字段的出现次数,判断是否重复。line_order:记录每个首字段首次出现的顺序,保证输出结果和原文件的行顺序一致。line_content:存储首字段唯一时的整行内容,一旦该字段重复出现,就删除对应的条目(因为重复的字段不需要保留任何一行)。- 最后按
line_order的顺序遍历,只输出那些还存在于line_content中的行——也就是首字段只出现过一次的行。
验证示例
用你提供的测试数据:
输入文件内容:
123456,23423,Smith,John,Jacob,Main St.,,Houston,78003 654321,54524,Smith,Jenny,,Main St.,,Houston,78003 332423,9023432,Gonzales,Michael,,Everyman,,Dallas,73423 123456,324324,Bryant,Kobe,,Special St.,,New York,2311 234324,232411,Willis,Bruce,,Sunset Blvd,,Hollywood,90210 438329,34233,Moore,Mike,,Whatever,,Detroit,92343 654321,43234,Smith,Jimbo,,Main St.,,Houston,78003
运行脚本后,输出结果和你期望的完全一致:
332423,9023432,Gonzales,Michael,,Everyman,,Dallas,73423 234324,232411,Willis,Bruce,,Sunset Blvd,,Hollywood,90210 438329,34233,Moore,Mike,,Whatever,,Detroit,92343
简化版(不关心行顺序)
如果不需要保留原文件的行顺序,还可以用更简洁的版本:
awk -F, '{ if (!($1 in lines)) lines[$1] = $0 else delete lines[$1] } END {for (k in lines) print lines[k]}' your_input.csv
这个版本逻辑更简单,但输出顺序是AWK数组的默认遍历顺序,可能和原文件不同。
内容的提问来源于stack exchange,提问作者J Thornton
相关产品推荐
相关产品推荐

