如何用Unix Shell脚本基于指定表头CSV提取目标列?
解决CSV按指定表头批量筛选列的Shell方案
针对你的28000列大CSV文件筛选需求,以下是无需额外安装工具、能正确处理CSV格式(含引号包裹的逗号字段)的两种实现方案:
方案一:利用Gawk的FPAT解析(推荐,Linux默认支持)
Gawk(大部分Linux服务器默认的awk版本)提供FPAT参数,可以精准匹配CSV字段(无论是普通字段还是引号包裹的字段)。
脚本代码
gawk -v header_file="你的表头文件名.csv" ' BEGIN { # 读取目标表头文件,假设每行一个列名(单行逗号分隔的话看下方修改提示) while ((getline line < header_file) > 0) { target_cols[line] = 1 } close(header_file) # 定义CSV字段匹配规则:双引号包裹的内容 或 非逗号内容 FPAT = "([^,]+)|(\"[^\"]+\")" } # 处理数据文件的表头行,记录目标列索引 NR == 1 { for (i=1; i<=NF; i++) { # 去掉字段的首尾引号 col_name = $i gsub(/^"|"$/, "", col_name) if (col_name in target_cols) { keep_cols[++num_keep] = i } } # 输出筛选后的表头 for (i=1; i<=num_keep; i++) { printf "%s%s", $keep_cols[i], (i==num_keep ? "\n" : ",") } next } # 处理所有数据行,输出目标列 { for (i=1; i<=num_keep; i++) { printf "%s%s", $keep_cols[i], (i==num_keep ? "\n" : ",") } } ' 你的数据文件名.csv > 输出结果.csv
适配修改
如果你的表头文件是单行逗号分隔的列名,将BEGIN块的读取逻辑替换为:
while ((getline line < header_file) > 0) { n = split(line, arr, /,/) for (j=1; j<=n; j++) { gsub(/^"|"$/, "", arr[j]) target_cols[arr[j]] = 1 } }
方案二:通用Awk脚本(兼容所有Awk版本)
如果服务器没有Gawk,用这个手动解析CSV字段的脚本,避免因引号内逗号导致的分割错误。
脚本代码
awk -v header_file="你的表头文件名.csv" ' BEGIN { # 读取目标表头(每行一个列名,单行分隔的话同上修改) while ((getline line < header_file) > 0) { target_cols[line] = 1 } close(header_file) FS = "" } # 自定义函数:解析一行CSV,返回字段数组和字段数 function parse_line(line, fields, n, in_quote, i, c) { n = 0 in_quote = 0 fields[++n] = "" for (i=1; i<=length(line); i++) { c = substr(line, i, 1) if (c == "\"") { in_quote = !in_quote fields[n] = fields[n] c } else if (c == "," && !in_quote) { fields[++n] = "" } else { fields[n] = fields[n] c } } return n } # 处理数据表头行 NR == 1 { n = parse_line($0, fields) for (i=1; i<=n; i++) { col_name = fields[i] gsub(/^"|"$/, "", col_name) if (col_name in target_cols) { keep_cols[++num_keep] = i } } # 输出筛选后表头 for (i=1; i<=num_keep; i++) { printf "%s%s", fields[keep_cols[i]], (i==num_keep ? "\n" : ",") } next } # 处理数据行 { n = parse_line($0, fields) for (i=1; i<=num_keep; i++) { printf "%s%s", fields[keep_cols[i]], (i==num_keep ? "\n" : ",") } } ' 你的数据文件名.csv > 输出结果.csv
备选:Python脚本(更可靠,处理复杂CSV)
如果服务器默认装有Python(无需额外安装),用原生csv模块处理是最稳妥的,支持所有CSV特殊格式(比如引号内换行的字段):
import csv # 读取目标表头集合 target_headers = set() with open("你的表头文件名.csv", "r") as f: reader = csv.reader(f) for row in reader: target_headers.update(row) # 筛选并输出结果 with open("你的数据文件名.csv", "r") as infile, open("输出结果.csv", "w") as outfile: reader = csv.DictReader(infile) writer = csv.DictWriter(outfile, fieldnames=target_headers) writer.writeheader() for row in reader: writer.writerow(row)
内容的提问来源于stack exchange,提问作者LucieCBurgess
相关产品推荐
相关产品推荐

