This can be done natively in Bash 4:
#!/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
Note that this approach is somewhat memory-inefficient; a more memory-efficient approach would sort the files before merging them (GNU sort is able to generate temporary files if the contents it's sorting can't fit in memory, and is thus more capable at this than any reasonable script we would write), and thus only need to store two lines at a time in memory:
#!/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
Also, this latter form does not require associative arrays, and will work with older versions of bash (or, with some adaptation, other shells).