我需要将两个文件合并为一个文件,其中包含两个文件中的所有列。
我提供我的示例文件。 文件1
chr loc T1 C1
chr1 100 2 3
chr1 200 3 4
chr2 100 1 4
chr2 400 3 1
文件2
chr loc T2 C2
chr1 100 1 2
chr1 300 4 1
chr2 100 7 5
chr2 500 1 9
输出文件应该是这样的
输出文件
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
答案1
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
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
sed
这里最棘手的部分是--join
只在单个字段上连接的原因,这里的连接标准是前 2 个字段。因此,我们必须将这些字段组合成一个单词:我用下划线替换第一个空格序列,这样 join 将看到chr1_100
,chr1_200
等。
join
要求对其输入文件进行排序。
我用流程替代这样就join
可以像文件一样与管道一起工作sed|sort
。
然后再次sed
调用以撤消组合字段,然后column
使其变得漂亮。
默认情况下,join
使用每个文件的第一个字段作为关键字段。
默认情况下,join
是否执行内部联接:仅打印两个文件中存在的密钥。-a1
and选项-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
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