我有很多文件(我以5为例)
如果与第一个文件不匹配,则应在输出中附加0
文件1
1001 1 2
1002 1 2
1003 3 5
1004 6 7
1005 8 9
1009 2 3
Run Code Online (Sandbox Code Playgroud)
文件2
1002 7
1003 8
Run Code Online (Sandbox Code Playgroud)
文件3
1001 5
1002 3
Run Code Online (Sandbox Code Playgroud)
文件4
1002 10
1004 60
1007 4
Run Code Online (Sandbox Code Playgroud)
文件5
1001 102
1003 305
1005 809
Run Code Online (Sandbox Code Playgroud)
期望的输出
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
Run Code Online (Sandbox Code Playgroud)
使用下面的代码,我可以合并两个文件,但是如何合并所有文件
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
Run Code Online (Sandbox Code Playgroud)
提前致谢
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
Run Code Online (Sandbox Code Playgroud)
选项-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"
Run Code Online (Sandbox Code Playgroud)
或者,如果您真的喜欢管道:
pipeline="cat /dev/null"
for file in f*; do pipeline="$pipeline | join -a1 -a2 -e0 -o auto - $file"; done
eval "$pipeline"
Run Code Online (Sandbox Code Playgroud)
这里很有意思: 我可以使用多少个管道?
注意:auto在这种情况下,的用法非常有用,但不是POSIX标准的一部分。它是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
Run Code Online (Sandbox Code Playgroud)
有关更多信息 man join
| 归档时间: |
|
| 查看次数: |
97 次 |
| 最近记录: |