我有三个类似的文件,它们都是这样的:
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。
答案 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]