这可以在 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
请注意,这种方法有点内存效率低下;一种更节省内存的方法会在合并文件之前对文件进行排序(如果它排序的内容无法放入内存中,GNU sort 能够生成临时文件,因此比我们编写的任何合理脚本都更有能力),因此只需要在内存中一次存储两行:
#!/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 一起使用(或者,经过一些调整,可以使用其他 shell)。