
У меня есть такой массив:
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
переменной.
У Гленна Джекмана было отличное замечание о повторяющихся числах, которое я не учел. Если вас интересуют только уникальные значения, вы можете использовать флаг -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"
Это все еще медленнее, чем вызов sort
, но имеет дополнительное преимущество, заключающееся в выборе строго меньшего второго по величине значения среди нескольких больших значений (таких как 7
и 7
выше).
решение3
Это хорошая работа для dc:
array=(1 2 7 6)
echo ${array[*]} | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'