如何用Bash统计CSV列唯一值并移除唯一值≤1的列
实现CSV列唯一值清洗的Bash脚本(适合初学者)
核心实现思路
参考通用CSV空列检测的逐列统计逻辑,分两步处理:
- 第一遍遍历全表,统计每一列的去重值总数,标记出唯一值数量≤1的列
- 第二遍遍历全表,输出时跳过所有被标记的待删除列,直接生成新的CSV内容
你给出的示例预期效果:原列A全为
1(唯一值数=1)、列C仅存在1种非空唯一值,两列均符合删除规则,最终保留B、D两列。
可直接使用的脚本
把下面内容保存为clean_csv.sh,运行时传入待处理的CSV文件名即可:
#!/bin/bash # 用法示例:./clean_csv.sh 待处理文件.csv > 输出文件.csv input_file="$1" awk -F ',' ' # 第一遍处理:统计每列非空值的唯一数量(可根据需求调整是否计入空值) NR == FNR { for (i = 1; i <= NF; i++) { # 空值不参与唯一值统计,去掉这行判断就会把空值算成1种唯一值 if ($i == "") continue dedup_key = i ":" $i if (!(dedup_key in seen_map)) { unique_col_count[i] += 1 seen_map[dedup_key] = 1 } } next } # 第二遍处理:输出时跳过待删除列 { final_line = "" for (i = 1; i <= NF; i++) { # 唯一值数量≤1的列直接跳过 if (unique_col_count[i] <= 1) continue final_line = (final_line == "" ? $i : final_line "," $i) } print final_line } ' "$input_file" "$input_file"
新手逐行说明
-F ','指定逗号为列分隔符,适配标准CSV格式- 我们把同一个输入文件传给awk两次,是文本处理常用的两遍扫描技巧:
- 第一次扫描时
NR == FNR条件成立(NR是累计处理的总行数,FNR是当前文件的行号,处理第一个文件时两者相等),只做唯一值统计,不输出内容 - 第二次扫描同一个文件时,FNR会重置行号,
NR == FNR不再成立,就走输出逻辑
- 第一次扫描时
- 去重逻辑:用
seen_map数组存储已经见过的「列号+列值」组合,遇到新组合就给对应列的唯一值计数加1 - 可调整规则:如果需要把空值也算入唯一值统计,删掉代码里
if ($i == "") continue这行就行;如果需要唯一值数≤2就删列,把判断条件里的<= 1改成<= 2即可
示例效果验证
输入的原始CSV内容:
A,B,C,D 1, 7, x, l 1, 3, , d 1, 2, , g 1, 6, , b 1, 8, x, j 1, 9, , y
运行脚本后输出的新CSV内容:
B,D 7, l 3, d 2, g 6, b 8, j 9, y
完全符合你提出的列删除规则。
内容的提问来源于stack exchange,提问作者bashnoob
相关产品推荐
相关产品推荐

