これはBash4でネイティブに実行できます。
#!/bin/bash
declare -A vals_one vals_two
while IFS=- read key val1 val2; do
if [[ ${vals_one["$key"]} ]] ; then
vals_one["$key"]=$(( ${vals_one["$key"]} + val1 ))
vals_two["$key"]=$(( ${vals_two["$key"]} + val2 ))
else
vals_one["$key"]=$val1
vals_two["$key"]=$val2
fi
done < <(cat input1.txt input2.txt)
for key in "${!vals_one[@]}"; do
printf '%s-%s-%s\n' "$key" "${vals_one[$key]}" "${vals_two[$key]}"
done
このアプローチはメモリ効率がやや悪いことに注意してください。よりメモリ効率の高いアプローチでは、ファイルをマージする前に並べ替えます(GNU並べ替えは、並べ替える内容がメモリに収まらない場合に一時ファイルを生成できるため、これを作成する合理的なスクリプトよりも優れています)、したがって、一度に2行をメモリに保存するだけで済みます。
#!/bin/bash
function merge_inputs {
IFS=- read key val1 val2
while IFS=- read new_key new_val1 new_val2; do
if [[ $key = "$new_key" ]] ; then
val1=$(( val1 + new_val1 ))
val2=$(( val2 + new_val2 ))
else
printf '%s-%s-%s\n' "$key" "$val1" "$val2"
key=$new_key
val1=$new_val1
val2=$new_val2
fi
done
printf '%s-%s-%s\n' "$key" "$val1" "$val2"
}
sort input1.txt input2.txt | merge_inputs
また、この後者の形式は連想配列を必要とせず、古いバージョンのbash(または、いくつかの適応により、他のシェル)で機能します。