Awk:匹配字段范围并生成匹配异常
我的文件的一个子集如下所示:Awk:匹配字段范围并生成匹配异常,awk,string-matching,Awk,String Matching,我的文件的一个子集如下所示: 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
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{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列是感兴趣的/,我们为a
定义的列的每个不同值分配一个键到数组b
:
for (i in a) if ($i!="./.") b[$i]`
print $1,(length(b)==1)
如果b
的长度为1,则表示感兴趣的列(不包括/
列)都具有相同的值。在这种情况下,我们打印行标题和1。如果它的长度与1不同,则打印行标题和0b
,为分析下一行做准备:
delete b
这正是我想要的。很好的解释。谢谢你,@john1024这是一个非常好的习惯用语awk。谢谢
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