基于列值筛选CSV行:保留region相同但Y、code不同的记录
按指定字段组合去重CSV文件的正确实现
需求:处理分号分隔的CSV文件,移除**第二列(region)、第六列(Y)、第七列(code)**三者值均相同的重复行;保留第二列值相同但第六列或第七列值不同的行。
输入示例
$ cat input.csv Name;region;latitude;longitude;X;Y;code;N USE;Cal;78676;8576;FDG;265;V;763 UTYE;Cal;56;8899;FDG;265;V;763 UKV;Cal;46;8576;FDG;265;R;763 UMV;Cal;785754;763;FDG;67;V;763 UBE;Cal;78676;8576;FDG;2651;V;763 UMV;mag;785754;763;FDG;67;V;763 UBE;mag;78676;8576;FDG;265;V;763
预期输出
$ cat output.csv Name;region;latitude;longitude;X;Y;code;N UKV;Cal;46;8576;FDG;265;R;763 UMV;Cal;785754;763;FDG;67;V;763 UBE;Cal;78676;8576;FDG;2651;V;763 UMV;mag;785754;763;FDG;67;V;763 UBE;mag;78676;8576;FDG;265;V;763
错误尝试分析
你之前的awk命令错误地以最后一列($NF)作为判断依据,完全没覆盖需求中的三个字段组合,导致记录重复且过滤逻辑不符合要求:
awk -F\; 'NR==1; $NF in a{if (a[$NF]!=0){print a[$NF];a[$NF]=0}print;next}{a[$NF]=$0}' input.csv
正确实现命令
核心思路是用region($2)、Y($6)、code($7)的组合作为唯一标识,通过数组记录该组合是否已出现,仅保留第一次出现的行:
awk -F';' 'NR==1 {print; next} !seen[$2,$6,$7]++' input.csv > output.csv
命令解释
-F';':指定CSV的字段分隔符为分号NR==1 {print; next}:直接打印表头行,不参与去重判断!seen[$2,$6,$7]++:- 数组
seen的键为$2、$6、$7的组合,用于标记该组合是否已出现 - 首次遇到该组合时,
seen[...]值为0,!0为真,执行打印;随后值自增为1 - 后续再遇到相同组合时,
!seen[...]为假,跳过打印
- 数组
内容的提问来源于stack exchange,提问作者TenEM
相关产品推荐
相关产品推荐

