合并两个表,包括多次出现的列标识符和唯一行

合并两个表,包括多次出现的列标识符和唯一行

我昨天问过类似的问题(合并两个表,包括多次出现的列标识符)但遇到了独特线条的问题。

我想根据第 1 列合并两个表:

文件一:

1 今天
1 绿色
2 明天
3 红色

文件2:

1 很多
1 有时
2 在工作中
2 在家里
2 有时
3 新的
4 很多
5 有时
6 在工作

期望输出(文件 3):

1 今天很多
1 今天有时
1 绿色很多
1 绿色有时
2 明天上班
2 明天在家
2 明天有时
3 红色 新

我想出了以下几点:

awk -F '[\t]' -v OFS='\t' '{i=$1;$1=x} NR==FNR{A[i]=$0;next} A[i]{print i,$0A[i]}' file2 file1 > file3

然而,它只给了我:

1 今天有时
2 明天有时
3 红色 新

请注意,上一个线程(join 和 awk)中的解决方案将为我提供两个文件(包括所有行)的组合。我只想包含文件 1 的行(第 1 列作为标识符),但报告文件 2 中的所有匹配项。

编辑:

列以制表符分隔

真实文件1:fig|395961.4.peg.2627 细菌蓝藻未知未知1795

(第 1 栏:图...第 2 栏:细菌...第 3 栏 1795)

真实文件 2:fig|1000561.3.peg.1838 半胱氨酸脱硫酶 (EC 2.8.1.7) 测试 - 硫胺素辅因子、维生素、辅基、色素

(第 1 列:图...第 2 列:半胱氨酸...第 3 列测试...)

答案1

我会在 Perl 中这样做:

#!/usr/bin/env perl 
use strict;

my (%file1,%file2);

## Open the 1st file
open(A,"file1");
while(<A>){
    ## Remove trailing newlines
    chomp; 
    ## Split the current line on tabs into the @F array.
    my @F=split(/\t/); 
    ## This is the tricky part. It adds fields 2-last
    ## to the hash $file1. The value of this hash is an array
    ## and the keys are the 1st fields. This will result in a list
    ## of all 1st fields and all their associated columns.
    push @{$file1{$F[0]}},@F[1..$#F];
} 


## Open the 2nd file
open(B,"file2");
while(<B>){
    ## Remove trailing newlines
    chomp; 
    ## Split the current line on tabs into the @F array.
    my @F=split(/\t/); 

    ## If the current 1st field was found in file1
    if (defined($file1{$F[0]})) {
        ## For each of the columns associated with
        ## this 1st field in the 1st file.
        foreach my $col (@{$file1{$F[0]}}) {
            print "$F[0]\t$col\t@F[1..$#F]\n";
        }
    }
} 

你可以把它打成(长)单线:

$ perl -lane 'BEGIN{open(A,"file1"); while(<A>){chomp; @F=split(/\t/); 
                    push @{$k{$F[0]}},@F[1..$#F];}  } 
              $k{$F[0]} && print "$F[0]\t@{$k{$F[0]}}\t@F[1..$#F]"' file2
1   today green a lot
1   today green sometimes
2   tomorrow    at work
2   tomorrow    at home
2   tomorrow    sometimes
3   red new

如果您正在处理大文件,请让它运行一段时间。

答案2

使用 awk

使用功能

清晰易读:

    awk 'function get(file,x,y) {
        while ( (getline < file) > 0) {if ($1==x)y,substr($0,index($0," ")+1)}
        close(file)
        }
        ARGV[1]==FILENAME{get(ARGV[2],$1,$0)}' file1 file2

单线:

awk 'function g(f,x,y){while((getline <f)>0)if($1==x){print y,substr($0,index($0," ")+1)}close(f)}NR==FNR{g(ARGV[2],$1,$0)}' file1 file2

使用数组

awk 'FNR==NR{a[$0]=$1;next}{for(i in a)if(a[i]==$1)print i,substr($0,index($0," ")+1)}' file file2

结果

1 today a lot
1 today sometimes
1 green a lot
1 green sometimes
2 tomorrow at work
2 tomorrow at home
2 tomorrow sometimes
3 red new

答案3

join 命令有什么问题?

加入文件1 文件2

给出所需的结果

相关内容