2012-12-03 43 views
2

我有此数组:Bash-总和从一行值的数组

array=(1 2 3 4 4 3 4 3) 

我可以得到数量最多:

echo "num: $(printf "%d\n" ${array[@]} | sort -nr | head -n 1)" 
#outputs 4 

但我想所有4的添加它们求和意思是我希望它输出12(4次出现3次)。有任何想法吗?

回答

3

使用AWK:

$ printf "%d\n" "${array[@]}" | sort -nr | awk 'NR>1 && p!=$0{print x;exit;}{x+=$0;p=$0;}' 
12 

使用类别,数量也以相反的(-R)顺序排序(-n),并且保持AWK直到它找到一个数,其是来自不同的数字求和前一个。

+0

感谢一位大师,大大提供帮助! – teutara

+0

+1。哈,当然,我以为你会需要两个循环,但因为它已经倒过来排序几乎微不足道:) –

2

你可以用awk做到这一点:

awk -v RS=" " '{sum[$0]+=$0; if($0>max) max=$0} END{print sum[max]}' <<<"${array[@]}" 

设置RS(记录分隔符)空间可以让你读你的数组项作为单独的记录。

sum[$0]+=$0;表示sum是每个输入值的累积和的映射; if($0>max) max=$0计算迄今为止所见的最大数量; END{print sum[max]}打印结尾处显示的大号码的总和。

<<<"${array[@]}"是一个在这里的文档,它允许你将一个字符串(在这个例子中是数组的所有元素)作为标准输入到awk

这种方式不涉及管道或循环 - 一个命令完成所有工作。

+0

+1,很好的使用awk的'RS'。你可以通过将if条件移动到一个新的分支来保存几个字符:'{sum [$ 0] + = $ 0} $ 0> max {max = $ 0}' –

+0

@glennjackman是的,但这是SO,不是代码高尔夫。 :) –

5
dc <<<"$(printf '%d\n' "${array[@]}" | sort -n | uniq -c | tail -n 1) * p" 
  1. sort在年底获得最大的价值
  2. uniq -c获得唯一的值,与他们有多少次出现
  3. tail计数只得到最后一行(与最大值和它的计数)
  4. dc到由计数相乘的值

我选择dc作为乘法步骤,因为它是RPN,因此您不必拆分uniq -c输出并在其中间插入任何东西 - 只需添加内容即可。

+0

awesoem马克里德,谢谢! – teutara

+1

+1只是因为你使用了'dc'而且我喜欢它! –

+0

+1不使用其他语言的拐杖 – Sorpigal

-1

只使用bash下

echo $((${array// /+})) 

Replace所有空格用加,并使用double-parentheses表达评估。

+0

这并不回答这个问题,即使我发现你的方法很酷。另外它不适合我。 但是'echo $(printf“%d +”$ {speeds [@]})0 | BC'做了诀窍。 – Titou