如何用Awk按列值差异筛选文本中的行三元组?
解决文本文件中三元组的Awk筛选问题
问题回顾
你需要筛选文本中由a开头行 + 两行s开头行组成的三元组,保留满足第二行s的第6列值 - 第一行s的第6列值 > 0的完整三元组。你的手动getline写法容易导致行处理混乱,咱们换一种更清晰可靠的方式实现。
错误脚本的问题分析
你的原脚本存在几个关键问题:
- 手动调用
getline会打乱Awk默认的行处理流程,尤其当文件结尾不完整时容易出错 - 零散存储每行字段的方式过于繁琐,直接保存整行更高效
- 末尾额外的
getline会跳过下一个三元组的起始行,导致逻辑错位 - 条件判断用了
>=0,但你的需求是“为正”(即>0),如果需要包含等于的情况可以调整
正确的Awk脚本实现
利用Awk的行号NR来分组处理固定结构的三元组,代码简洁且逻辑清晰:
awk ' # 保存a开头的行(每3行的第一行) NR%3 == 1 { a_line = $0 } # 保存第一个s行的内容和第6列值(每3行的第二行) NR%3 == 2 { s1_line = $0; s1_col6 = $6 } # 处理第二个s行(每3行的第三行) NR%3 == 0 { if ($6 - s1_col6 > 0) { print a_line print s1_line print $0 print "" # 可选:添加空行分隔不同三元组,方便阅读 } }' myfile.txt
脚本工作原理
NR%3 == 1:当行号是3的倍数+1时(第1、4、7...行),将当前a行完整存入变量a_lineNR%3 == 2:当行号是3的倍数+2时(第2、5、8...行),保存第一个s行的完整内容和第6列数值NR%3 == 0:当行号是3的倍数时(第3、6、9...行),计算当前s行第6列与第一个s行第6列的差值,若结果为正,则打印整个三元组
测试输出结果
用你提供的输入文件运行脚本后,会输出以下符合条件的三元组(最后一个三元组因差值为负被过滤):
a score=2910 EG2=0 E=0 s MJUT01042700.1 17232 3459 + 53939 s scaffold1|size190226 11711 3461 + 190226 a score=1427 EG2=0 E=0 s MJUT01011585.1 1110178 1852 + 1659926 s scaffold1|size190226 96228 1834 + 190226 a score=1136 EG2=0 E=0 s MJUT01033992.1 44701 1369 + 67673 s scaffold1|size190226 96715 1347 + 190226 a score=1074 EG2=0.02 E=0 s MJUT01027223.1 115853 1482 + 196715 s scaffold1|size190226 140742 1471 + 190226
内容的提问来源于stack exchange,提问作者Corsair
相关产品推荐
相关产品推荐

