perl - 命令行枢轴

标签 perl bash awk pivot-table gawk

过去几天我一直在寻找一组命令行工具,一个 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

请注意,每个“单元格”在数据集中只有一个值(即,与电子表格一样,行“1”列“A”没有任何重复项)

我已经尝试过各种用于转置数据的 awk shell 实现 - 但似乎无法让它们工作。我的一个想法是将每个“Col”值剪切到一个单独的文件中,然后使用“join”命令行将它们按“Row”重新组合在一起——但必须有一种更简单的方法。我确信这做起来非常简单 - 但我有点挣扎。

我的输入文件有 A 到 G 列(主要包括可变长度字符串)和 10,000 行。如果我可以避免将所有内容加载到内存中,那将是一个巨大的优势。

为知道答案的任何人邮寄啤酒!

一如既往 - 非常感谢您的帮助。

干杯,

乔希

附注- 我有点惊讶没有开箱即用的命令行实用程序来执行这种非常基本的枢轴/换位操作。我看了http://code.google.com/p/openpivot/http://code.google.com/p/crush-tools/这两者似乎都需要聚合计算。

最佳答案

我可以在 gawk 中执行此操作,但不能在 nawk 中执行此操作。

#!/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 行的效果如何,但我怀疑如果您有足够的内存,就没问题。我看不出如何通过将内容存储在稍后加入的单独文件中来避免将内容加载到内存中 except。这几乎是虚拟内存的手动实现。

更新:

根据评论:

#!/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 $ 

关于perl - 命令行枢轴,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9475806/

相关文章:

javascript - 为什么在解码 URI 编码的 JSON 字符串时会收到错误 "unexpected end of string while parsing JSON string"?

bash - 如何查看/bin/sh 指向的内容

python - 自动化终端条目

regex - Perl正则表达式从任意集合中查找字符

linux - 如何使用 perl SOAP::Lite 输出 soap 片段?

bash - 我怎样才能让 awk 为它解析的每个文件处理 BEGIN block ?

linux - 删除符合特定条件的行

linux - 在 linux 中使用分隔符 "/"拆分文件

perl - 如何使用 Perl 检查远程服务器上是否存在文件?

linux - 这个 Bash 函数有语法错误吗?当硬编码到主循环中时,功能可以正常工作