将两个文件合并为具有合并列的单个文件

Nar*_* DJ 2 shell text-processing join

我需要将两个文件合并为一个文件,其中包含两个文件中的所有列。

我正在提供我的示例文件。 文件 1

chr loc T1  C1
chr1    100 2   3
chr1    200 3   4
chr2    100 1   4
chr2    400 3   1
Run Code Online (Sandbox Code Playgroud)

档案 2

chr loc T2  C2
chr1    100 1   2
chr1    300 4   1
chr2    100 7   5
chr2    500 1   9
Run Code Online (Sandbox Code Playgroud)

和输出文件应该是这样的

输出文件

chr loc T1  C1  T2  C2
chr1    100 2   3   1   2
chr1    200 3   4   0   0
chr1    300 0   0   4   1
chr2    100 1   4   7   5
chr2    400 3   1   0   0
chr2    500 0   0   1   9
Run Code Online (Sandbox Code Playgroud)

gle*_*man 5

join -a1 -a2 -e 0 -o 0,1.2,1.3,2.2,2.3 \
    <(sed 's/ \+/_/' file1 | sort) \
    <(sed 's/ \+/_/' file2 | sort) | 
sed 's/_/ /' | 
column  -t | 
sort
Run Code Online (Sandbox Code Playgroud)
chr   loc  T1  C1  T2  C2
chr1  100  2   3   1   2
chr1  200  3   4   0   0
chr1  300  0   0   4   1
chr2  100  1   4   7   5
chr2  400  3   1   0   0
chr2  500  0   0   1   9
Run Code Online (Sandbox Code Playgroud)

这里最棘手的部分是原因sed--join只会加入一个字段,这里的加入条件是前 2 个字段。因此,我们必须对这些领域的合并成一个字:我更换空白的第一序列以下划线所以加入会看到chr1_100chr1_200等等。

join 要求对其输入文件进行排序。

我使用进程替换,以便join可以使用sed|sort文件等管道。

然后再次sed调用以撤消组合字段,然后column使其变得漂亮。

默认情况下,join使用每个文件的第一个字段作为关键字段。

默认情况下,join是否进行内部联接:仅打印两个文件中存在的键。在-a1-a2选项来启用完整外部联接我们想要的。该-e选项为空字段提供默认值,我们需要该-o选项来指定我们想要所有字段。


也可以使用awk:

awk '
    {key = $1 OFS $2} 
    NR == FNR {f1[key] = $3; f2[key] = $4; next} 
    !(key in f1) {print $1, $2, 0, 0, $3, $4; next} 
    {print key, f1[key], f2[key], $3, $4; delete f1[key]} 
    END {for (key in f1) print key, f1[key], f2[key], 0, 0}
' file1 file2 | sort
Run Code Online (Sandbox Code Playgroud)
chr loc T1 C1 T2 C2
chr1 100 2 3 1 2
chr1 200 3 4 0 0
chr1 300 0 0 4 1
chr2 100 1 4 7 5
chr2 400 3 1 0 0
chr2 500 0 0 1 9
Run Code Online (Sandbox Code Playgroud)