我有四个不同的文件:file1、file2、file3、file4。每个文件都有 2 个不同的列,用制表符分隔。我想将 file1 的第一列(作为参考)与第二个文件、第三个和第四个文件的第一列进行匹配,并打印匹配的第一列和每个文件的具有匹配第一列的第二列。文件看起来像:
文件1
Bm1_00085|Bm1_22625 0.263974289
Bm1_00087|Bm1_22620 0.663443490
文件2
Bm1_00085|Bm1_22625 0
Bm1_57630|Bm1_52870 0
文件3
Bm1_57630|Bm1_54855 0
Bm1_00085|Bm1_22625 4
文件4
Bm1_57630|Bm1_52870 0
Bm1_00085|Bm1_22625 1
输出:
Bm1_00085|Bm1_22625 0.263974289 0 4 1
答案1
有了join
一个足够聪明的 shell 知道如何处理<(...)
:
join <(sort file1) <(sort file2) | join - <(sort file3) | join - <(sort file4)
输出:
Bm1_00085|Bm1_22625 0.263974289 0 4 1
答案2
这是使用 awk 实现的一种方法:
解析.awk
# Use the first column of the first file as a key and the second column
# as a value in the h hash
NR==FNR { h[$1] = $2; next }
# If $1 is a key in h append $2 to h[$1]
$1 in h { h[$1] = h[$1] OFS $2 }
# When the input has been exhausted, print h key value pairs
# that contain more than one element
END { for(k in h)
if(split(h[k], a) > 1)
print k OFS h[k]
}
像这样运行它:
awk -f parse.awk file1 file2 file3 file4
输出:
Bm1_00085|Bm1_22625 0.263974289 0 4 1
答案3
在 Perl 中,完成这项工作的工具是哈希。哈希是一组键值对,这使得这种交叉引用变得非常容易。
注意 - 这将仅有的如果第一个字段是唯一的,则有效:
#!/usr/bin/env perl
use strict;
use warnings;
my %data;
while (<>) {
my ( $key, $value ) = split;
push( @{ $data{$key} }, $value );
}
foreach my $key ( sort keys %data ) {
if ( @{ $data{$key} } >= @ARGV ) {
print join( "\t", $key, @{ $data{$key} } ), "\n";
}
}
调用为myscript.pl file1 file2 file3 file4
.
它:
- 通过 读取命令行中的文件列表
<>
,并打开它们进行处理。 - 一次迭代一行,将该行拆分为
$key
和$value
。 存储
$value
在数组的哈希中。遍历哈希中的每个键
- 如果元素数量 >= 命令行参数数量(例如文件数量) - 则打印该行。
输出是:
Bm1_00085|Bm1_22625 0.263974289 0 4 1
笔记:
假定所有文件中都有唯一的“键”。