重新排列文本文件中的唯一行

时间:2014-07-27 11:28:12

标签: perl awk uniq

我有一个txt文件,如下所示 输入文件:test.txt

AC1   CAFA
AC2   CGSD
AC3   FGGB
AC1   GHSH
AC2   GHSR
AC1   FGR

我的预期输出:sum(属于第3列的行数)

AC1   CAFA,GHSH,FGR  3
AC2   CGSD,GHSR  2
AC3   FGGB  1

我首先尝试使用awk:

 awk '{line="";for (i = 2; i <= NF; i++) line = line $i ","; table[$1]=table[$1] line;}
      END {for (key in table) print key "\t" table[key];}' test.txt | sort

6 个答案:

答案 0 :(得分:0)

你刚刚错过了剧本中的计数器:

awk '{count[$1]++;line="";for (i = 2; i <= NF; i++) line = (line == "") ? $i : line "," $i; table[$1] = ($1 in table) ? line : table[$1] "," line;}
     END {for (key in table) print key "\t" table[key] "\t" count[key];}' test.txt | sort

答案 1 :(得分:0)

awk -v OFS='  ' '{ ++counter[$1] } $1 in a { a[$1] = a[$1] "," $2; next } { a[$1] = $2; keys[i++] = $1 } END { for (i = 0; i in keys; ++i) { key = keys[i]; print key, a[key], counter[key] } }' file

输出:

AC1  CAFA,GHSH,FGR  3
AC2  CGSD,GHSR  2
AC3  FGGB  1

脚本版本:

#!/usr/bin/awk -f
BEGIN {
    OFS = "  "
}
{
    if ($1 in a) {
        a[$1] = a[$1] "," $2
    } else {
        a[$1] = $2
        keys[i++] = $1
    }
    ++counter[$1]
}
END {
    for (i = 0; i in keys; ++i) {
        key = keys[i]
        print key, a[key], counter[key]
    }
}

答案 2 :(得分:0)

$ cat tst.awk
{ vals[$1] = (cnt[$1]++ ? vals[$1] "," : "") $2 }
END { for (key in vals) print key, vals[key], cnt[key] }

$ awk -f tst.awk file
AC2 CGSD,GHSR 2
AC3 FGGB 1
AC1 CAFA,GHSH,FGR 3

如果您希望输出按键值排序,请使用GNU awk:

$ cat tst.awk
BEGIN { PROCINFO["sorted_in"] = "@ind_str_asc" }
{ vals[$1] = (cnt[$1]++ ? vals[$1] "," : "") $2 }
END { for (key in vals) print key, vals[key], cnt[key] }

$ gawk -f tst.awk file
AC1 CAFA,GHSH,FGR 3
AC2 CGSD,GHSR 2
AC3 FGGB 1

或只是管道到sort

答案 3 :(得分:0)

以下是perl变体:

perl -lane '
    push @{$h{$F[0]}}, $F[1] 
}{ 
    print join " ", $_, join (",", @{$h{$_}}), scalar @{$h{$_}} for sort keys %h' file
AC1 CAFA,GHSH,FGR 3
AC2 CGSD,GHSR 2
AC3 FGGB 1
  • 我们使用-a选项将空格上的行拆分为数组。填充的数组是@F
  • 我们使用column1作为键,并通过将column2作为值列表来创建数组哈希。
  • END块中,我们打印密钥,该密钥的值列表和计数。
  • -n选项创建一个while循环,一次读取一行的整个文件。
  • -l选项会选中新行并在打印期间将其放回原处。
  • -e选项告诉perl执行代码。

答案 4 :(得分:0)

这是您可能喜欢的一点Perl解决方案。它期望输入文件作为命令行上的参数。

所有这一切都是在空格上分割文件的每一行,并填充哈希%data,其中键AC1AC2等与所有相应数组的引用相关该键的值。一旦填充了哈希,就很容易以所需的形式转储数据。

use strict;
use warnings;

my %data;

while (<>) {
  my ($key, $val) = split;
  push @{ $data{$key} }, $val;
}

for my $key (sort keys %data) {
  my $list = $data{$key};
  local $" = ',';
  printf "%s   %s  %d\n", $key, "@$list", 0+@$list;
}

<强>输出

AC1   CAFA,GHSH,FGR  3
AC2   CGSD,GHSR  2
AC3   FGGB  1

答案 5 :(得分:-1)

由于您有perl标记:

#! /usr/bin/perl -an

$h{$F[0]} = [] unless exists $h{$F[0]};
push @{h{$F[0]}},$F[1];

END {
    foreach $key (sort keys %h) {
        $out=$key."\t"; $c=0;
        foreach ( @{$h{$key}} ) {
            $out.=$_.",";
            $c++
        }
        $out=~s/,$//;
        print "$out $c\n";
    }
}

输出:

perl test.pl file
AC1 CAFA,GHSH,FGR 3
AC2 CGSD,GHSR 2
AC3 FGGB 1

说明:

1。 #! /usr/bin/perl -an -a使用默认值自动拆分输入     字段分隔符,它创建数组@F

2. 然后我们使用field1作为键创建一个哈希,并将值作为数组引用,我们将为给定键存储field2。

哈希看起来像这样:

$VAR1 = {
          'AC3' => [
                     'FGGB'
                   ],
          'AC2' => [
                     'CGSD',
                     'GHSR'
                   ],
          'AC1' => [
                     'CAFA',
                     'GHSH',
                     'FGR'
                   ]
        };

第3 即可。然后我们就这样打印了。