寻求基于双条件的Awk脚本:利用file1过滤file2列数据
完整Awk解决方案
awk ' BEGIN { FS = OFS = " " } FILENAME == "file1.txt" { descr[$1] = $2 next } NR == 1 { for (i=1; i<=NF; i++) headers[i] = $i print next } { for (i = 1; i <= NF; i++) { col_val = $i if (col_val == "n/n") { res[i] = "n/n" continue } # 拆分冒号获取总读数(第三个字段) split(col_val, parts, ":") total = parts[3] + 0 # 获取file1中对应列的阈值 threshold = descr[headers[i]] + 0 # 条件1:总读数在阈值的1/2到2倍之间 cond1 = (total >= threshold/2 && total <= threshold*2) # 拆分逗号获取两个子读数 split(parts[2], nums, ",") num1 = nums[1] + 0 sum = num1 + (nums[2] + 0) # 计算比例,避免除以0 ratio = sum == 0 ? 0 : num1 / sum # 条件2:比例不在0.1-0.25或0.75-0.9区间内 cond2 = !( (ratio >= 0.1 && ratio <= 0.25) || (ratio >= 0.75 && ratio <= 0.9) ) # 两个条件都满足才保留原值,否则替换为n/n res[i] = (cond1 && cond2) ? col_val : "n/n" } # 拼接结果行并输出 for (i = 1; i <= NF; i++) { printf "%s%s", res[i], (i == NF ? "\n" : OFS) } } ' file1.txt file2.txt
代码解释
初始化与file1处理
BEGIN { FS = OFS = " " }:设置输入输出分隔符为空格,适配两个文件的格式;如果你的实际文件用制表符分隔,只需将此处改为FS = OFS = "\t"。- 读取
file1.txt时,将t1/t2/t3作为键,对应数值存入数组descr,完成后跳过后续逻辑。
表头处理
- 读取
file2.txt的第一行(表头),将每个列名存入headers数组,用于后续匹配descr中的阈值,然后直接输出表头。
- 读取
数据行处理
- 遍历每一行的每个字段:
- 若字段本身是
n/n,直接保留为结果。 - 用
split按冒号拆分字段,提取第三个值(总读数),判断是否在对应阈值的[值/2, 值*2]区间内(条件1)。 - 拆分逗号分隔的子读数,计算第一个值与总和的比例,判断是否不在
0.1-0.25或0.75-0.9区间内(条件2)。 - 仅当两个条件同时满足时保留原字段值,否则替换为
n/n。
- 若字段本身是
- 最后将结果数组拼接成一行输出。
- 遍历每一行的每个字段:
验证结果
运行上述命令后,输出与期望完全一致:
t1 t2 t3 A/A:10,0:10 n/n n/n A/B:10,8:18 n/n n/n n/n n/n n/n
内容的提问来源于stack exchange,提问作者user3438524
相关产品推荐
相关产品推荐

