awk脚本未生效:如何删除特定列值全部相同的行?
问题描述
我有一个16列的制表符分隔文件:
0/0;20,20 0/1;20,20 0/0;20,20 0/1;20,20 0/0;20,20 0/1;20,20 0/1;20,20 0/1;20,20 0/1;20,20 0/1;20,20 0/1;20,20 0/1;20,20 0/1;20,20 0/1;20,20 0/1;20,20 0/1;20,20 0/0;11,11 0/2;11,6 0/0;11,11 0/2;11,6 0/0;11,11 0/1;11,6 0/3;11,6 0/2;11,6 0/2;11,6 0/1;11,6 0/2;11,6 0/1;11,6 0/1;11,6 0/1;11,6 0/1;11,6 0/1;11,6 0/0;12,12 0/1;12,10 0/0;12,12 0/1;12,10 0/0;12,12 0/1;12,10 0/1;12,10 0/1;12,10 0/1;12,10 0/1;12,10 0/1;12,10 0/1;12,10 0/1;12,10 0/1;12,10 0/1;12,10 0/1;12,10 0/0;43,43 0/1;43,44 0/0;43,43 0/1;43,44 0/0;43,43 0/1;43,44 0/1;43,44 0/1;43,44 0/1;43,44 0/1;43,44 0/1;43,44 0/1;43,44 0/1;43,44 0/1;43,44 0/1;43,44 0/1;43,44 0/0;10,10 0/0;10,10 0/0;10,10 0/0;10,10 0/0;10,10 0/0;10,10 0/0;10,10 0/1;10,9 0/0;10,10 0/0;10,10 0/0;10,10 0/1;10,9 0/2;10,11 0/0;10,10 0/0;10,10 0/1;10,9
我需要删除第2列、第4列以及第6至16列所有值均相同的整行,只保留这些列中存在差异的行。尝试了以下命令:
awk -F'\t' '!a[$2 $4 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16]++' test.txt
但该命令输出了所有行,预期仅输出两行存在指定列差异的行:
0/0;11,11 0/2;11,6 0/0;11,11 0/2;11,6 0/0;11,11 0/1;11,6 0/3;11,6 0/2;11,6 0/2;11,6 0/1;11,6 0/2;11,6 0/1;11,6 0/1;11,6 0/1;11,6 0/1;11,6 0/1;11,6 0/0;10,10 0/0;10,10 0/0;10,10 0/0;10,10 0/0;10,10 0/0;10,10 0/0;10,10 0/1;10,9 0/0;10,10 0/0;10,10 0/0;10,10 0/1;10,9 0/2;10,11 0/0;10,10 0/0;10,10 0/1;10,9
解决方案
原命令逻辑错误:它是基于指定列的组合值跨行去重,只保留第一次出现的行,但你的需求是判断单行内的第2、4、6-16列是否全部相同,而非跨行去重。
正确的思路是:对每一行,以第2列的值为基准,检查第4列、第6到16列的所有值是否都和基准一致。只要有一个列的值和基准不同,就保留该行;否则删除。
可以用以下awk命令实现:
awk -F'\t' '{ base = $2 same = 1 # 检查第4列是否与基准一致 if ($4 != base) same = 0 # 遍历检查第6到16列 for (i=6; i<=16; i++) { if ($i != base) { same = 0 break } } # 存在不同值则输出当前行 if (!same) print $0 }' test.txt
命令说明
- 提取第2列的值作为基准
base; - 初始化
same为1(假设所有目标列都和基准相同); - 先检查第4列,若和基准不同则标记
same为0; - 循环遍历第6到16列,只要发现某列和基准不同,立即标记
same为0并跳出循环; - 最后如果
same为0(即存在不同值),就输出当前行。
这个命令会准确筛选出你需要的两行结果。
内容的提问来源于stack exchange,提问作者pedro
相关产品推荐
相关产品推荐

