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"
очень интересный здесь: Есть ли ограничение на количество труб, которые я могу использовать?
Примечание: использование 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
Дополнительная информация о man join