我有很多文件(我以5个为例)
如果与第一个文件不匹配,则应在输出中附加 0
文件1
1001 1 2
1002 1 2
1003 3 5
1004 6 7
1005 8 9
1009 2 3
文件2
1002 7
1003 8
文件3
1001 5
1002 3
文件4
1002 10
1004 60
1007 4
文件5
1001 102
1003 305
1005 809
需要的输出
1001 1 2 0 5 0 102
1002 1 2 7 3 10 0
1003 3 5 8 0 0 305
1004 6 7 0 0 60 0
1005 8 9 0 0 0 809
1007 0 0 0 0 4 0
1009 2 3 0 0 0 0
使用下面的代码我可以合并两个文件,但是如何合并所有文件
awk 'FNR==NR{a[$1]=$2;next}{print $0,a[$1]?a[$1]:"0"}' file2 file1
1001 1 2 0
1002 1 2 7
1003 3 5 8
1004 6 7 0
1005 8 9 0
提前致谢
最佳答案
GNU 加入救援!
$ join -a1 -a2 -e '0' -o auto file1 file2 \
| join -a1 -a2 -e '0' -o auto - file3 \
| join -a1 -a2 -e '0' -o auto - file4 \
| join -a1 -a2 -e '0' -o auto - file5
选项 -a1
和 -a2
告诉 join
插入缺失的字段。 -e '0'
告诉它用零替换它们。输出由 -o auto
指定,它假定采用所有字段。
当有大量文件时,不能使用管道结构,但可以使用简单的 for 循环:
out=output
tmp=$(mktemp)
[[ -e "$out" ]] && rm -rf "$out" || touch "$out"
for file in f*; do
join -a1 -a2 -e0 -o auto "$out" "$file" > "$tmp"
mv "$tmp" "$out"
done
cat "$out"
或者如果你真的喜欢管道:
pipeline="cat /dev/null"
for file in f*; do pipeline="$pipeline | join -a1 -a2 -e0 -o auto - $file"; done
eval "$pipeline"
这里非常有趣: Is there a limit on how many pipes I can use?
备注: auto
的用法在这种情况下非常有用,但不是 POSIX standard 的一部分.它是一个 GNU 扩展,是 GNU coreutils 的一部分。 .纯 POSIX 版本会读起来有点麻烦:
$ join -a1 -a2 -e '0' -o 0 1.2 2.2 file1 file2 \
| join -a1 -a2 -e '0' -o 0 1.2 1.3 2.2 - file3 \
| join -a1 -a2 -e '0' -o 0 1.2 1.3 1.4 2.2 - file4 \
| join -a1 -a2 -e '0' -o 0 1.2 1.3 1.4 1.5 2.2 - file5
关于 man join
的更多信息
关于bash - 根据匹配列合并多个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55919150/