我有一个看起来像这样的文件:
aaa 15
aaa 12
bbb 131
bbb 12
ccc 123
ddddd 1
ddddd 2
ddddd 3
我想像这样得到左侧每个独特元素的总和,并计算每个元素的总百分比:
aaa 27 - 9%
bbb 143 - 48%
ccc 123 - 41%
ddddd 6 - 2%
我如何在BASH中完成此任务?
答案 0 :(得分:3)
由于我找不到任何正确的副本,我正在发布答案。随意报告一个好的,所以我将删除我的答案并关闭为重复。
awk '{count[$1]+=$2} END {for (i in count) print i, count[i]}' file
这将创建一个数组count[key]=value
,用于跟踪给定键的值。最后,它遍历值并打印它们。
它返回:
aaa 27
ccc 123
bbb 143
ddddd 6
要显示百分比,只需跟踪总和并相应地划分:
awk '{tot+=$2; count[$1]+=$2}
END {for (i in count)
printf "%s %d - %d%%\n", i, count[i], (count[i]/tot)*100
}' file
所以你可以得到:
aaa 27 - 9%
ccc 123 - 41%
bbb 143 - 47%
ddddd 6 - 2%
答案 1 :(得分:0)
由于你要求Bash,这里有一个Bash≥4解决方案(关联数组需要Bash≥4):
#!/bin/bash
declare -Ai sums
while read -r ref num; do
# check that num is a valid number or continue
[[ $num = +([[:digit:]]) ]] || continue
sums[$ref]+=$(( 10#$num ))
done < file
for ref in "${!sums[@]}"; do
printf '%s %d\n' "$ref" "${sums[$ref]}"
done
输出未排序;通过sort
(或使用排序算法)对其进行排序。
所以现在你添加了百分比要求!我希望你不要再编辑这个问题,进一步添加更多东西......
一旦我们得到了关联数组sums
,我们就可以求和:
sum=0
for x in "${sums[@]}"; do ((sum+=x)); done
并打印百分比:
for ref in "${!sums[@]}"; do
printf '%s %d - %d%%\n' "$ref" "${sums[$ref]}" "$((100*${sums[$ref]}/sum))"
done
答案 2 :(得分:0)
bash
3的解决方案,没有关联数组:
while read key value
do
keys=$(echo -e "$keys\n$key")
var=data_$key
(($var=${!var}+$value))
((total=total+$value))
done < input_file
unique=$(echo "${keys:1}" | sort -u)
while read key
do
var=data_$key
((percentage=100*${!var} / total))
echo "$key $percentage%"
done <<EOF
$unique
EOF
更改为使用间接变量引用,而不是更传统的eval
。