使用AWK处理文件列:实现除法、log2计算并解决重复行及除零问题
问题描述
有一个三列文本文件,需忽略表头行,计算第3列除以第2列的结果作为第4列,再计算第4列的log2值作为第5列。使用AWK脚本处理时出现重复行、结果缺失,还触发division by zero attempted错误。
输入文件示例(my_file.txt)
head my_file.txt this is header chrX:73829232:-::chrX:73831065:- 76.5382 76.34220209 chrX:73827985:-::chrX:73829067:- 60.0702 62.1887549 chr11:18266979:+::chr11:18269194:+ 15.4004 1558.282058
当前脚本及错误输出
awk -v OFS='\t' 'FNR > 1 {$4 = $3 / $2}1' my_file.txt |awk -F"\t" 'FNR > 1{a = log($4)/log(2); print $0"\t" a} OFS="\t"'
错误输出:
awk: cmd. line:1: (FILENAME=my_file.txt FNR=15) fatal: division by zero attempted this is header chrX:73829232:-::chrX:73831065:- 76.5382 76.3422020852288 0.997439 -0.00369948 chrX:73829232:-::chrX:73831065:- 76.5382 76.3422020852288 0.997439 chrX:73827985:-::chrX:73829067:- 60.0702 62.1887548960591 1.03527 0.0500071 chrX:73827985:-::chrX:73829067:- 60.0702 62.1887548960591 1.03527
预期输出
this is my desired header chrX:73829232:-::chrX:73831065:- 76.5382 76.34220209 0.9974392145 -0.003699170995 chrX:73827985:-::chrX:73829067:- 60.0702 62.1887549 1.035267985 0.05000426549 chr11:18266979:+::chr11:18269194:+ 15.4004 1558.282058 101.1845185 6.66084476
问题原因
- 重复行:第一个awk脚本中
{...}1会无条件打印所有行,包括表头和处理后的数据行;第二个awk脚本重复处理数据行,且OFS="\t"位置错误,导致部分行重复输出。 - 除零错误:文件中存在第2列值为0的行,直接计算
$3/$2触发错误。 - 结果缺失:第二个awk脚本仅处理
FNR>1的行,但第一个awk已输出处理后的行,导致部分行未添加log2值。
正确解决方案
用单个awk脚本完成所有操作,同时添加除零判断:
awk -v OFS='\t' ' BEGIN { print "this is my desired header" } FNR > 1 { if ($2 == 0) { $4 = "NA" $5 = "NA" } else { $4 = $3 / $2 $5 = log($4)/log(2) } print $0 } ' my_file.txt
脚本说明
BEGIN块:直接输出自定义表头,替换原表头。FNR>1:跳过原文件的表头行。- 除零判断:避免触发除零错误,可根据需求设置默认值(示例中设为
NA)。 - 单脚本处理:避免管道导致的重复行和数据不一致问题,直接在同一脚本中计算第4、5列并打印。
运行后将得到与预期一致的输出,无重复行、无除零错误,列数完整。
内容的提问来源于stack exchange,提问作者Shafaque Zahra
相关产品推荐
相关产品推荐

