基于列特定条件的Awk输出:保留结构并置空不匹配字段
Awk 解决方案:按列条件筛选并处理分号分隔表格数据
针对你需要处理分号分隔、含日期列的19列数据需求,以下是可灵活配置条件的Awk脚本,支持小于、大于、区间三种判断,同时保留原表格结构,将不满足指定列条件的字段置空,仅输出至少有一个字段符合条件的行(适配MacOS环境)。
核心脚本(filter.awk)
BEGIN { FS = ";" OFS = ";" # 配置列条件:key为列号(从2开始,$1是日期),value为条件字符串 # 条件格式: # - 小于:lt:阈值 (例:cols[2] = "lt:100" → 第2列数值<100) # - 大于:gt:阈值 (例:cols[3] = "gt:80" → 第3列数值>80) # - 区间:range:最小值:最大值 (例:cols[4] = "range:50:150" → 第4列数值>50且<150) cols[2] = "lt:100" cols[3] = "gt:80" cols[4] = "range:50:150" # 可继续添加第5到19列的条件 } { has_match = 0 # 保留日期列($1)不变 output = $1 # 遍历第2到19列 for (i=2; i<=19; i++) { field = $i empty = 0 # 未配置条件的列默认保留原字段 # 如果该列有配置条件,执行判断 if (i in cols) { split(cols[i], cond, ":") op = cond[1] val1 = cond[2] val2 = cond[3] # 转换字段为数值(非数值字段会被转为0) num = +field empty = 1 # 配置条件的列默认置空,仅满足条件时保留 if (op == "lt" && num < val1) { empty = 0 has_match = 1 } else if (op == "gt" && num > val1) { empty = 0 has_match = 1 } else if (op == "range" && num > val1 && num < val2) { empty = 0 has_match = 1 } } # 拼接输出内容 if (empty) { output = output OFS "" } else { output = output OFS field } } # 仅输出至少有一个匹配条件的行 if (has_match) { print output } }
使用说明
- 修改条件配置:打开
filter.awk,修改BEGIN块中的cols数组,根据需求为对应列设置判断条件(支持同时为多列配置不同条件)。 - 执行命令:在终端运行(兼容MacOS默认的BSD Awk):
awk -f filter.awk 你的数据文件.txt
输入输出示例验证
输入示例(data.txt)
2024-05-20;120;90;160;25;... 2024-05-21;90;90;100;30;... 2024-05-22;150;60;40;20;...
配置条件
cols[2] = "lt:100" cols[3] = "gt:80" cols[4] = "range:50:150"
输出结果
2024-05-20;;90;;25;... 2024-05-21;90;90;100;30;...
- 第一行:第2列120不满足
lt:100(置空),第3列90满足gt:80(保留),第4列160不满足区间(置空),未配置条件的列(如第5列)保留原数值;因存在匹配字段,该行输出。 - 第二行:所有配置条件的列均满足,全部保留,该行输出。
- 第三行:无字段满足配置条件,不输出。
脚本特性
- 兼容MacOS默认的BSD Awk,无需额外安装Gawk
- 条件配置灵活,可随时切换小于/大于/区间判断逻辑
- 未配置条件的列自动保留原字段值,仅处理指定列
- 自动过滤无匹配条件的行,仅输出有效数据
内容的提问来源于stack exchange,提问作者anlom
相关产品推荐
相关产品推荐

