我有多个 .txt 文件,希望根据第一列(数字)将它们合并在一起,如果有任何丢失的数据,请填写“NULL”。
文件_1:
1 a
2 b
3 c
文件_2:
3 c
4 d
5 e
文件_3:
4 d
5 e
6 f
预期输出:
1 a NULL NULL
2 b NULL NULL
3 c c NULL
4 NULL d d
5 NULL e e
6 NULL NULL f
join -t $'\t' -a 1 -a 2 -1 1 -2 1 -e NULL -o 0,1.2,2.2 file_1 file_2 | join -t $'\t' -a 1 -a 2 -1 1 -2 1 -e NULL - file_3 > expected_output
这个命令给了我第 1、2 和 3 列的正确输出;但是,第 4 列中缺少“NULL”,知道如何修复它吗?还有没有更好的方法来合并多个文件而不是编写超长管道命令?
答案1
扩展所学到的东西https://stackoverflow.com/a/13963634和弗拉桑
这适用于任意数量的文件。
#!/bin/bash
tempdir=$(mktemp --directory)
trap "rm -r $tempdir" EXIT SIGTERM
for infile in "$@"; do
sort "$infile" > "${tempdir}/${infile}.sorted"
if [ -e "${tempdir}/final.results" ]
then
join -a1 -a2 -e "NULL" -o auto \
"${tempdir}/final.results" "${tempdir}/${infile}.sorted" \
> "${tempdir}/res"
mv "${tempdir}/res" "${tempdir}/final.results"
else
cp "${tempdir}/${infile}.sorted" "${tempdir}/final.results"
fi
done
cat "${tempdir}/final.results"
结果:
$ . join_multiple_files.sh file* | column -t
1 a NULL NULL
2 b NULL NULL
3 c c NULL
4 NULL d d
5 NULL e e
6 NULL NULL f
答案2
你快到了。使用您的命令,我们得到:
$ join -t $'\t' -a 1 -a 2 -1 1 -2 1 -e NULL -o 0,1.2,2.2 file_1 file_2 | join -t $'\t' -a 1 -a 2 -1 1 -2 1 -e NULL - file_3
1 a NULL
2 b NULL
3 c c
4 NULL d d
5 NULL e e
6 f
join
行只是没有相同数量的列,因为我们没有为管道中的右侧设置格式。
如果我们将其添加为-o 0,1.2,1.3,2.2
(连接字段 + 第一个连接的第二列和第三列 + 的第二列file_3
):
$ join -t $'\t' -a 1 -a 2 -1 1 -2 1 -e NULL -o 0,1.2,2.2 file_1 file_2 | join -t $'\t' -a 1 -a 2 -1 1 -2 1 -e NULL -o 0,1.2,1.3,2.2 - file_3
1 a NULL NULL
2 b NULL NULL
3 c c NULL
4 NULL d d
5 NULL e e
6 NULL NULL f
最后,如果我们可以假设 的 GNU 实现join
,我们可以让它完成推断正确格式的工作,并使用-o auto
代替-o 0,1.2,2.2
和-o 0,1.2,1.3,2.2
,前提是对于每个文件,所有行最多具有与第一个文件相同的字段数。引用 info join
:
-o auto
如果指定了关键字auto
,则从每个文件的第一行推断输出格式。这与默认输出格式相同,但也确保每行输出相同数量的字段。缺失的字段将被选项替换-e
,多余的字段将被丢弃。