加入3个文件的第一个列加入(是awk)?

时间:2010-05-12 04:00:07

标签: bash unix awk text-files

我有三个类似的文件,它们都是这样的:

档案A

ID1 Value1a
ID2 Value2a
  .
  .
  .
IDN Value2n

我想要一个像这样的输出

输出

ID1 Value1a Value1b Value1c
ID2 Value2a Value2b Value2c
.....
IDN ValueNa ValueNb ValueNc

查看第一行,我希望value1A是fileA中id1的值,value1B是fileB中id1的值,依此类推,每个字段和每一行。我认为它像一个SQL连接。我已经尝试了几件事,但其中没有一件甚至接近。

编辑:所有文件都有相同的长度和ID。

4 个答案:

答案 0 :(得分:9)

尝试join(1)

join fileA fileB | join - fileC

答案 1 :(得分:2)

更新:该问题已经过编辑,表明所有文件都包含所有密钥,因此接受的答案(join)肯定比这个更好。如果密钥可能不在所有文件中,则只考虑使用此密钥。


如果你不是关注性能,你可以尝试快速和肮脏:

$ cat file_a
    ID5 Value5a
    ID1 Value1a
    ID3 Value3a
    ID4 Value4a
    ID2 Value2a
$ cat file_b
    ID1 Value1b
    ID3 Value3b
$ cat file_c
    ID2 Value2c
    ID3 Value3c
    ID4 Value4c
    ID5 Value5c
$ cat qq.sh
    #!/bin/bash
    keylist=$(awk '{print $1'} file_[abc] | sort | uniq)
    for key in ${keylist} ; do
        val_a=$(grep "^${key} " file_a | awk '{print $2}') ; val_a=${val_a:--}
        val_b=$(grep "^${key} " file_b | awk '{print $2}') ; val_b=${val_b:--}
        val_c=$(grep "^${key} " file_c | awk '{print $2}') ; val_c=${val_c:--}
        echo ${key} ${val_a} ${val_b} ${val_c}
    done
$ ./qq.sh
    ID1 Value1a Value1b -
    ID2 Value2a - Value2c
    ID3 Value3a Value3b Value3c
    ID4 Value4a - Value4c
    ID5 Value5a - Value5c

这实际上会先解决密钥,然后使用该密钥从每个文件中获取值,如果不在相关文件中,则为-

如果文件更复杂(如果字段1不在行的开头或后面是非空格分隔符),则需要调整grep命令,但这应该是合理的先行解决方案。在这种情况下可能使用grep

grep "^[ X]*${key}[ X]"

其中X实际上是 tab 字符,因为它允许在键之前使用零或多个空格或制表符以及用于终止键的空格或制表符。

如果文件特别大,您可能需要考虑使用awk中的关联数组,但由于没有大小的指示,我会从这个开始,直到你到达它的运行速度太慢了。

答案 2 :(得分:2)

join(丹尼斯的答案)更好,但只是为了踢,这就是我在awk中提出的:

awk '{a=$0; getline b <"fileB"; getline c <"fileC"; $0=a" "b" "c; print $1,$2,$4,$6}' <fileA

答案 3 :(得分:1)

只是要添加为了使连接工作,应该对输入进行排序。 这个awk解决方案应该处理任意数量的输入文件。 您还将丢失密钥的原始顺序(您需要更多代码来保留它)。

awk 'END {
  for (K in k) print K, k[K]
    }
{ 
  k[$1] = k[$1] ? k[$1] FS $2 : $2 
  }' file1 file2 [.. filen]