如何删除重复列并合并其唯一值

时间:2014-12-19 13:44:07

标签: bash perl awk sed scripting

我想转换包含以下值的源文件:

col1|col2|col3
1|a|desc1
1|a|desc2
1|b|desc3
1|b|desc4
1|b|desc5
2|c|desc6
2|c|desc7

成:

col1|col2|col3
1|a|desc1 desc2
1|b|desc3 desc4 desc5
2|c|desc6 desc7

它基本上是第1列和第2列的重复删除,但它们的第3列将被合并。查看awk或perl或sed或bash代码 - 以最小的处理能耗为准。

4 个答案:

答案 0 :(得分:2)

这是一个awk-oneliner,进行合并并保持顺序:

awk -F'|' '{k=$1FS$2;if(a[k])a[k]=a[k] OFS $3;else{a[k]=$0;b[++i]=k}}
           END{for(x=1;x<=i;x++)print a[b[x]]}' file

答案 1 :(得分:2)

$ cat tst.awk
BEGIN { FS="|" }
{
    curr = $1 FS $2
    if (curr == prev) {
        rec = rec " " $3
    }
    else {
        if (rec) print rec
        rec = $0
    }
    prev = curr
}
END { if (rec) print rec }

$ awk -f tst.awk file
col1|col2|col3
1|a|desc1 desc2
1|b|desc3 desc4 desc5
2|c|desc6 desc7

答案 2 :(得分:1)

这是一个perl解决方案:

open $fh, "<", "yourfile.txt";
%h = ();
$head = <$fh>;

while (<$fh>) {
    if ($_ =~ /(\d\|[a-z]\|)(.*)/) {
        $h{$1} .= "$2 ";
    }
}

print $head;
foreach (sort keys %h) {
    print "$_$h{$_}\n";
}

您可以使用正则表达式获取合并的col1col2并将其存储为散列键,然后将col3值附加到该键,同时循环覆盖其余部分文件。

答案 3 :(得分:1)

来自命令行的Perl,

perl -lne'
  /(.+\|)(.+)/ or next;
  $h{$1} or push @r, $1;
  push @{ $h{$1} }, $2;

  END { print $_, "@{$h{$_}}" for @r }
' file