我的文件的子集如下所示:
row1 ./. 1/1 1/1 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 1/1 0/0 0/0 0/0 0/0 ./. 1/1 0/0 0/0
row2 ./. 0/0 0/0 0/0 0/0 0/0 0/0 0/0 ./. 0/0 0/0 0/0 ./. 0/0 0/0 0/0 0/0 0/0 ./. 0/0 ./. ./.
row3 ./. 0/1 0/0 0/0 0/0 1/2 5/6 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 ./. 1/1 0/0 0/0
row4 ./. 1/1 1/1 0/0 0/0 0/0 0/0 1/6 0/0 ./. 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 ./. 1/1 0/1 0/0
row5 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0 0/0
值格式为n / n,其中n可以等于数字(0-9)或句点(。)
我的目标: 如果第2,3,4,20和21列相同,则返回1,否则返回0.如果列相同,则包含“./。”的列。被忽略,返回1,否则返回0。
示例所需输出:
row1 0
row2 1
row3 0
row4 0
row5 1
第二行收到“1”,因为虽然有一些“./。”的实例。在我想要比较的列中,感兴趣的列中的所有其他值都是相同的。第五行收到“1”,因为感兴趣的列中的所有值都相同。
我写了这个,这部分地做了我想要的(它不包括所有必要的字段组合):
awk 'BEGIN{OFS=" "}{sign="";{if ( ($2==$3 || $2=="./." || $3=="./.") && ($2==$4 || $4=="./.") && ($2==$20 || $20=="./.") && ($2==$21 || $21=="./.")) {sign="1 "}else{sign="0 "}}; print $2, $3, $4, $20, $21, sign}'test.txt
我的全尺寸文件有更多列需要包含在匹配中;有没有更简洁的方式来写这个?
答案 0 :(得分:2)
$ awk 'BEGIN{a[2];a[3];a[4];a[5];a[21]} {for (i in a) if ($i!="./.") b[$i]; print $1,(length(b)==1); delete b}' test.txt
row1 0
row2 1
row3 0
row4 0
row5 1
或者,对于喜欢将代码分布在多行中的人来说:
awk '
BEGIN{
a[2];a[3];a[4];a[5];a[21]
}
{
for (i in a)
if ($i!="./.")
b[$i]
print $1,(length(b)==1)
delete b
}' test.txt
数组a
确定我们检查的列:
a[2];a[3];a[4];a[5];a[21]
这将用于表示感兴趣的是2,3,4,5和21列。
只要列值不是b
,我们就会为a
定义的列的每个不同值为数组./.
分配一个键:
for (i in a) if ($i!="./.") b[$i]`
我们打印出结果:
print $1,(length(b)==1)
如果b
的长度为1,则表示感兴趣的列(不包括./.
列)都具有相同的值。在这种情况下,我们打印行标题和1.如果它的长度不同于1,我们打印行标题和0。
最后,我们删除b
以准备分析下一行:
delete b
$ awk -v x='2 3 4 5 21' 'BEGIN{split(x,a)} {for (i in a) if ($a[i]!="./.") b[$a[i]]; print $1,(length(b)==1); delete b}' test.txt
row1 0
row2 1
row3 0
row4 0
row5 1