如何比较awk中的列对?

时间:2015-11-07 00:13:12

标签: awk

我从成对分析中得到以下数据集(第一行只是样本ID):

A B A C
1 1 1 0
1 2 1 1
1 0 1 2

我希望比较field 1field 2然后field 3field 4的值,以便我每次都要打印行号NR查看我正在检查的对的12组合。

例如对于AB对,我想要输出:

A B 2

对于对AC,我想要输出:

A C 3

我想逐行进行,所以我可能需要代码包括:

for i in {1..3}; do
    awk 'NR=="'${i}'" {code}'
done

但我不知道如何以成对的方式进行(即比较field 1field 2然后field 3field 4等......)。

我该怎么做?

2 个答案:

答案 0 :(得分:4)

很难用这么小的例子说,但这可能是你想要的:

$ cat tst.awk
FNR==1 {
    for (i=1;i<=NF;i++) {
        name[i] = $i
    }
    next
}
{
    for (i=1;i<NF;i+=2) {
        if ( ($i == 1) && ($(i+1) == 2) ) {
            print name[i], name[i+1], NR-1
        }
    }
}

$ awk -f tst.awk file
A B 2
A C 3

答案 1 :(得分:1)

你当然应该只运行一次脚本;没有必要更频繁地运行awk。目前尚不清楚如何打印多个匹配项。但是,如果您在某个时间线上工作,那么输出可能会一次出现一行。

在此基础上工作,然后:

awk 'NR == 1 { for (i = 1; i < NF; i += 2)
               { cols[(i+1)/2,1] = $i; cols[(i+1)/2,2] = $(i+1); } 
               next
             }
             { for (i = 1; i < NF; i += 2)
               { if ($i == 1 && $(i+1) == 2)
                     print cols[(i+1)/2,1], cols[(i+1)/2,2], NR - 1
               }
             }'

NR == 1代码块捕获标题,以便可以在主打印代码中使用它们。还有很多其他方法来存储信息。另一个代码块查看数据行并检查字段对是否包含1 2,如果匹配则打印出控制数据。因为NF是偶数,但循环数是奇数,<比较是可以的。通常在awk中,您使用for (i = 1; i <= NF; i++)只需一个增量,然后<=才能获得正确的行为。

对于您的最小数据集,这会产生:

A B 2
A C 3

对于这个更大的数据集:

A B A C
1 1 1 0
1 2 1 1
1 0 1 2
1 2 4 2
5 3 1 9
7 0 3 2
1 2 1 0
9 0 1 2
1 2 3 2

代码生成:

A B 2
A C 3
A B 4
A B 7
A C 8
A B 9