过去几天我一直在寻找一套命令行工具,一个perl或一个awk脚本,可以让我快速转换以下数据:
Row|Col|Val
1|A|foo
1|B|bar
1|C|I have a real
2|A|bad
2|C|hangover
进入这个:
A|B|C
foo|bar|I have a real
bad||hangover
请注意,每个" cell"的数据集中只有一个值。 (即,与电子表格一样,没有任何重复的行" 1" Col" A")
我尝试过各种用于转置数据的awk shell实现 - 但似乎无法让它们正常工作。我的一个想法就是削减每一个" Col"将值转换为单独的文件,然后使用" join"命令行将它们重新组合在一起#34; Row" - 但必须有一个更简单的方法。我确信这样做非常简单 - 但我有点挣扎。
我的输入文件有Cols A到G(主要包括可变长度字符串)和10,000行。如果我可以避免将所有内容加载到内存中,这将是一个巨大的优势。
任何能够得到答案的人都可以通过邮件发送啤酒!
一如既往 - 非常感谢您的帮助。
干杯,
乔什P.S。 - 我有点惊讶的是,没有开箱即用的命令行util来执行这种非常基本的转轴/转置操作。我查看了http://code.google.com/p/openpivot/和http://code.google.com/p/crush-tools/这两个似乎都需要汇总计算。
答案 0 :(得分:3)
我可以用gawk做到这一点,但不能发牢骚。
#!/usr/local/bin/gawk -f
BEGIN {
FS="|";
}
{
rows[$1]=1; cols[$2]=1; values[$1][$2]=$3;
}
END {
for (col in cols) {
output=output sprintf("|%s", col);
}
print substr(output, 2);
for (row in rows) {
output="";
for (col in cols) {
output=output sprintf("|%s", values[row][col]);
}
print substr(output, 2);
}
}
它甚至有效:
ghoti@pc $ cat data
1|A|foo
1|B|bar
1|C|I have a real
2|A|bad
2|C|hangover
ghoti@pc $ ./doit.gawk data
A|B|C
foo|bar|I have a real
bad||hangover
ghoti@pc $
我不确定这对10000行有多好,但我怀疑如果你有记忆,你会没事的。我无法看到如何通过将内容存储在您稍后加入的单独文件中来避免将内容加载到内存(除外)中。这几乎是虚拟内存的手动实现。
<强>更新强>
每条评论:
#!/usr/local/bin/gawk -f
BEGIN {
FS="|";
}
{
rows[$1]=1; cols[$2]=1; values[$1,$2]=$3;
}
END {
for (col in cols) {
output=output sprintf("|%s", col);
}
print output;
for (row in rows) {
output="";
for (col in cols) {
output=output "|" values[row,col];
}
print row output;
}
}
输出:
ghoti@pc $ ./doit.awk data
|A|B|C
1|foo|bar|I have a real
2|bad||hangover
ghoti@pc $
答案 1 :(得分:1)
只需使用哈希。
如果您不想将它们加载到内存中,则可能需要DBM::Deep
和DBM后端等模块。
my %table;
my $maxa = 'A';
my $maxr = 0;
<>;
while (<>) {
chomp;
my ($a,$b,$c) = split /\|/;
$table{$a}->{$b} = $c;
$maxr = $a if ($a > $maxr);
$maxa = $b if ($b gt $maxa);
}
for (my $c = 'A' ; $c lt $maxa ; $c++) {
print $c . '|';
}
print "$maxa\n";
for (my $r = 1 ; $r <= $maxr ; $r++) {
for (my $c = 'A' ; $c lt $maxa ; $c++) {
print $table{$r}->{$c} . '|';
}
print $table{$r}->{$maxa} . "\n";
}
答案 2 :(得分:1)
如果你知道Awk,我建议你看看Perl。 Perl比Awk强大得多。优点是,如果您了解BASH / Bourne shell和Awk,Perl中的大部分语法都会很熟悉。
Perl的另一个好处是整个CPAN存储库,它允许您下载已编写的Perl模块以在您的程序中使用。在CPAN中快速搜索Data::Pivot看起来(很快就会看到)它可能会做你想要的。
如果没有,请查看Acme::Tools pivot命令。或者尝试其中一个many others。
其他人已经提供了一些解决方案,但我建议您查看CPAN Perl存档的内容。对于像这样的事情来说,这是一个非常强大的工具。