查找具有相同列的行'成对文件

时间:2016-01-21 17:18:31

标签: regex bash perl awk

我们说我有这个制表符分隔的文件

id1 term1 term2
id2 term1 term2
id3 tern2 term3

我想要做的是计算相同column2 column3次出现的次数以及它们引用的ID。

因此新的制表符分隔文件将如下所示:

term1 term2 2 id1,id2
term2 term3 1 id3

我尝试过这种单线,这是我最接近所需解决方案的

awk '{count[$2,$3]++;} END {for (word in count) printf("%s\t%s\n", word,count[word])}'

但我得到的是:

term1 term2 2
term2 term3 1

和术语之间的矩形。

Perl或awk或其他任何想法都很可爱。

起初我认为Perl会更好但是我的朋友建议awk。这是我第一次使用awk。

3 个答案:

答案 0 :(得分:2)

此解决方案按您的要求执行

数组@pairs的唯一目的是保留输入数据的顺序。如果没有必要,那么代码可以大大减少

我假设给定的第2列/第3列值可能会出现多次具有相同ID的值。这意味着我必须将该对的出现次数与累积相关ID分开计算。如果不是这样,则计数只是每对的ID数

use strict;
use warnings;
use feature 'say';

my %pairs;
my @pairs;

while ( <> ) {

    chomp;
    my ($id, $pair) = split "\t", $_, 2;

    push @pairs, $pair unless $pairs{$pair};

    ++$pairs{$pair}{count};
    $pairs{$pair}{ids}{$id} = 1;
}

for my $pair ( @pairs ) {
    my ($n, $ids) = @{ $pairs{$pair} }{qw/ count ids /};
    say join "\t", $pair, $n, join(',', keys %$ids);
}

输出

term1 term2 2   id1,id2
tern2 term3 1   id3

答案 1 :(得分:1)

您可以使用awk

awk -f script.awk input.file

script.awk 的位置如下:

{
    # Select and count the terms combination
    terms=$2" "$3
    count[terms]++

    # Concatenate ids by `,` - except if it
    # is the first occurrence
    ids[terms]=ids[terms] ? ids[terms]","$1 : $1
}
END{
    # At the end print the desired results
    for(terms in count){
        print terms,count[terms],ids[terms]
    }
}

答案 2 :(得分:1)

用于真正的2D数组的GNU awk:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{ ids[$2 FS $3][$1] }
END {
    for (key in ids) {
        printf "%s\t%s", key, length(ids[key])
        sep = OFS
        for (i in ids[key]) {
            printf "%s%s", sep, i
            sep = ","
        }
        print ""
    }
}
$ awk -f tst.awk file
tern2   term3   1       id3
term1   term2   2       id1,id2