Решение с bash
, join
, paste
и плохим вкусом:
#! /usr/bin/env bash
if [ $# -lt 3 ]; then exit 1; fi
files=( '' "$@" )
declare -a temps
for ((i=0; i<=$#; i++)); do
[ $i -eq 0 -o -f "${files[$i]}" ] || exit 1
temps[$i]=$( mktemp -t "${0##*/}"_$$_XXXXXXXX ) || exit 1
done
trap 'rm -f "${temps[@]}"' EXIT HUP INT QUIT TERM
cat "$@" | sort -u >"${temps[0]}"
TAB=$( printf '\t' )
for ((i=1; i<=$#; i++)); do
join -j1 -a1 -t"$TAB" "${temps[0]}" <(paste "${files[$i]}" "${files[$i]}") | \
sed "/^[^$TAB]\$/ s/\$/$TAB/" >"${temps[$i]}"
done
printf '%s' ${files[1]}
for ((i=2; i<=$#; i++)); do
printf '\t%s' ${files[$i]}
let j=i-1
let k=i-2
join -j1 -t"$TAB" "${temps[$j]}" "${temps[$i]}" >"${temps[$k]}"
cat "${temps[$k]}" >"${temps[$i]}"
done
printf '\n'
cut -d "$TAB" -f 2- <"${temps[$#]}" | sort -n
За исключением последнего sort -n
, все это работает с любыми текстовыми элементами, а не с числами, если они не содержат табуляции (но TAB
можно заменить на любой другой разделитель). Кроме того, это можно было бы сделать с помощью всего 3 временных файлов и некоторого перемешивания вещей (но это только усугубило бы дурной вкус).