Unix 基于第一列合并两个文件并保持顺序

Unix 基于第一列合并两个文件并保持顺序,unix,Unix,如何基于第一列连接两个文件并保留第二个文件的顺序 文件1: ID1 123 ID2 234 ID3 232 ID4 344 ID5 345 ID6 867 文件2 ID2 A C ID3 G T ID1 C T ID4 A C ... 因此,合并的文件应如下所示: ID2 234 A C ID3 232 G T ID1 123 C T ID4 344 A C ... id是第一列的值(出现在两个文件中)。文件1的行/ID比文件2多。 文件2中的所有IDs都在文件1中,但并非文件1中

如何基于第一列连接两个文件并保留第二个文件的顺序

文件1:

ID1 123
ID2 234
ID3 232
ID4 344
ID5 345
ID6 867
文件2

ID2 A C
ID3 G T
ID1 C T
ID4 A C
...
因此,合并的文件应如下所示:

ID2 234 A C 
ID3 232 G T 
ID1 123 C T 
ID4 344 A C 
...
id
是第一列的值(出现在两个文件中)。文件1的行/ID比文件2多。
文件2中的所有
ID
s都在文件1中,但并非文件1中的所有
ID
s都在文件2中

您逐行读取这两个文件,并通过正则表达式提取行标记。提取的令牌存储在关联数组中,使用第一个令牌作为密钥。在第二步中,您可以循环遍历所有可用的键,并从数组中存储的值构造输出行

php中的示例实现,仅供演示。因此,不会进行错误检查,而且可能必须根据您的需要调整模式。显然,在所有其他语言中都可以做到这一点。我选择php是因为它很容易阅读:

<?php
$input_file[1]=fopen('/path/input1.list','r');
$input_file[2]=fopen('/path/input2.list','r');

# read input files line by line
foreach ($input_file as $input){
    while (!feof($input)){
        $tokens=array();
        preg_match('/^(ID[0-9]+) (.+)$/',trim(fread($input)),$tokens);
        $list[$i][$tokens[1]]=$tokens[2];
   } 
}

# construct output lines:
$output_file=fopen('/path/output.list','w');
foreach ($list[1] as $key=>$val){
    $line=sprintf("%s %s%s\n", $key, $val, 
                  array_key_exists($key,$list[2])?' '.$list[2][$key]:'' );
    fwrite($output_file,$line);
}

# some house keeping
fclose($input_file[1]);
fclose($input_file[2]);
fclose($output_file);

?>


(请注意,我没有检查这个,我只是写下了这个。它是一个起点,还没有准备好使用)

这里有一种使用
awk
的方法:

awk 'FNR==NR { a[$1]=$2; next } $1 in a { print $1, a[$1], $2, $3 }' file1 file2
结果:

ID2 234 A C
ID3 232 G T
ID1 123 C T
ID4 344 A C

使用
连接

$ join file1.txt file2.txt

ID1 123 C T
ID2 234 A C
ID3 232 G T
ID4 344 A C
注意:首先需要对文件进行排序,这不会保持file2.txt的顺序,但如果您不在意的话,这是最干净的方式

先对文件进行预排序:
sortfile1.txt-o file1.txt;排序file2.txt-o file2.txt

执行连接:
joinfile1.txt file2.txt


通常,您可以
join file1.txt file.txt | sort
并根据某些条件进行排序,但在这种情况下,
file2.txt
不会按任何列/条件进行排序

+1条漂亮的单行线。但是,如果文件1太大,请注意内存消耗。的可能重复