在unix中转置文件

时间:2010-10-13 07:56:48

标签: linux unit-testing unix grep

我有类似这样的文件

1111,K1
2222,L2
3333,LT50
4444,K2
1111,LT50
5555,IA
6666,NA
1111,NA
2222,LT10

需要的输出

1111,K1,LT50,NA
2222,L2,LT10
3333,LT50
4444,K2
5555,IA
6666,NA

第1列列号可以随时重复,但我需要的输出是sort和uniq

4 个答案:

答案 0 :(得分:5)

awk -F"," '{a[$1]=a[$1]FS$2}END{for(i in a) print i,a[i]}' file | sort

如果您有一个大文件,您可以尝试每隔几行打印一次,例如50000

BEGIN{FS=","}
{ a[$1]=a[$1]FS$2 }
NR%50000==0 {
  for(i in a) { print  a[i] }
  delete a  #delete array so it won't take up memory
}
END{
  for(i in a){ print a[i] }
}

答案 1 :(得分:2)

使用非标准工具SQLite shell是一个可以理解的尝试。数据库在内存中。

echo    'create table tmp (a int, b text);
        .separator ,
        .import file.txt tmp
        .output out.txt
        SELECT a, group_concat(b) FROM tmp GROUP BY a ORDER BY a ASC;
        .output stdout
        .q' | sqlite

答案 2 :(得分:1)

这是python中的解决方案。脚本从标准输入读取数据。

#!/usr/bin/env python
import sys
d = {}
for line in sys.stdin.readlines():
  pair = line.strip().split(',')
  d[pair[0]] = d.get(pair[0], [])
  d[pair[0]].append(str(pair[1]))
for key in sorted(d):
  print "%s,%s" % (key, ','.join(d[key]))

答案 3 :(得分:0)

这是Perl中的一个,但它不会特别有效:

#!/usr/bin/perl -w
use strict;
my %lines;
while (<>) {
    chomp;
    my ($key, $value) = split /,/;
    $lines{$key} .= "," if $lines{$key};
    $lines{$key} .= $value;
}

my $key;
for $key in (keys(%lines)) {
    print "$key,$lines{$key}\n";
}

像这样使用:

$ ./command <file >newfile

尽管如此,你可能会有更好的运气。我没有时间为你写这个。这是一个大纲:

  1. 抓取并从文件中删除第一行。
  2. 解析文件的其余部分,连接任何匹配的行并将其删除。
  3. 在文件末尾输出新的长行。
  4. 如果文件仍有内容,请循环回1。