我有一个字符串列表(stdin),如下一个:
1 pineapples
28 apples
16 oranges
8 apples
2 apples
2 oranges
56 pineapples
是否有本地方式(例如sort
& uniq -c
),我可以将其合并并将它们相加:
38 apples
18 oranges
57 pineapples
与sort |uniq -c
类似,但不仅仅是出现次数?
答案 0 :(得分:13)
试试这个:
awk '{a[$2] += $1} END{for (i in a) print a[i], i}' < in.txt
输出
38 apples
57 pineapples
18 oranges
答案 1 :(得分:4)
使用GNU datamash
:
$ <file datamash -Wst' ' -g2 sum 1
apples 38
oranges 18
pineapples 57
(-W
使用空格表示输入字段分隔符,-t' '
使用空格表示输出字段分隔符,-s
排序输入,-g2
组第2列,{{1}来自每个组中第1列的值。)
这里不是一个大赢家(超过sum 1
),但它确实对更复杂的统计操作有所启发(例如计算组中位数,方差,偏度等)。
要获得有问题的格式(如果这很重要),我们需要手动反转输出字段的顺序,因为awk
始终首先输出分组列:
datamash
答案 2 :(得分:0)
Awk是这项工作的合适工具。但是,对于那些不熟悉awk且bash版本> gt = 4.0的人来说,这是一个带有bash associative arrays的替代版本。这将读取文件Fruits的每一行,并使用第二列作为键存储数字。
declare -A Sumarray
while IFS=" " read num thing
do
if [[ -v Sumarray[$thing] ]]
then
Sumarray[$thing]=$(( ${Sumarray[$thing]} + $num ))
else
Sumarray[$thing]=$num
fi
done < Fruits
$ for K in "${!Sumarray[@]}"; do echo ${Sumarray[$K]} $K ; done
38 apples
57 pineapples
18 oranges
答案 3 :(得分:0)
使用awk
对输出求和并排序:
awk '{
items[$2]+=$1
}
END {
asorti(items, sorted)
for(i in sorted)
print items[sorted[i]] " " sorted[i]
}' input_file
仅使用bash
:
declare -A items=()
while read -r num item; do
((items[$item] += num))
done < input_file
sorted=()
while IFS= read -r -d '' item; do
sorted+=("$item")
done < <(printf '%s\0' "${!items[@]}" | sort -z)
for index in "${sorted[@]}"; do
echo "${items[$index]} $index"
done