我有一个像这样的数组:
array=(1 2 7 6)
并想搜索第二大的值,输出为
secondGreatest=6
有什么办法可以在 bash 中做到这一点吗?
答案1
printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1
在其自己的行上打印数组的每个值,对其进行排序,获取最后 2 个值,删除最后一个值
secondGreatest=$(printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1)
将该值设置为secondGreatest
变量。
格伦·杰克曼(Glenn Jackman)关于重复数字的观点非常精彩,但我没有考虑到。如果您只关心唯一值,您可以使用-u
排序标志:
secondGreatest=$(printf '%s\n' "${array[@]}" | sort -nu | tail -2 | head -1)
答案2
通过数组进行特定于 bash 的循环就可以做到这一点;你必须跟踪最大的和第二大的。唯一棘手的部分是在初始化这些值时要小心;最大值被初始化为第一个元素;当我们第一次看到小于最大值的值时,第二大值就会被初始化。随后,对于第二大值,我们仅在它严格小于当前最大值时才更新它:
#!/bin/bash
array=(7 7 6 2 1)
if [ "${#array[@]}" -lt 2 ]
then
echo Incoming array is not large enough >&2
exit 1
fi
largest=${array[0]}
secondGreatest='unset'
for((i=1; i < ${#array[@]}; i++))
do
if [[ ${array[i]} > $largest ]]
then
secondGreatest=$largest
largest=${array[i]}
elif (( ${array[i]} != $largest )) && { [[ "$secondGreatest" = "unset" ]] || [[ ${array[i]} > $secondGreatest ]]; }
then
secondGreatest=${array[i]}
fi
done
echo "secondGreatest = $secondGreatest"
它仍然比调用 to 慢sort
,但它具有在面对多个高值(例如7
和7
以上)时选择严格较小的第二大值的额外好处。
答案3
这对 dc 来说是一份好工作:
array=(1 2 7 6)
echo ${array[*]} | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'