
Tengo una matriz como esta:
array=(1 2 7 6)
y le gustaría buscar el segundo valor más grande, siendo el resultado
secondGreatest=6
¿Hay alguna manera de hacer esto en bash?
Respuesta1
printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1
Imprima cada valor de la matriz en su propia línea, ordénelo, obtenga los últimos 2 valores, elimine el último valor
secondGreatest=$(printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1)
Establezca ese valor en la secondGreatest
variable.
Glenn Jackman tuvo un excelente comentario sobre los números duplicados que no consideré. Si solo te importan los valores únicos, puedes usar la -u
bandera de clasificación:
secondGreatest=$(printf '%s\n' "${array[@]}" | sort -nu | tail -2 | head -1)
Respuesta2
Un bucle específico de bash a través de la matriz podría hacerlo; tienes que realizar un seguimiento del más grande y del segundo más grande. La única otra parte complicada es tener cuidado al inicializar esos valores; el valor más grande se inicializa en el primer elemento; el segundo valor más grande se inicializa la primera vez que vemos un valor que es menor que el valor más grande. Posteriormente, para el segundo valor más grande, solo lo actualizamos si es estrictamente menor que el valor más grande actual:
#!/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"
Sigue siendo más lento que llamar a sort
, pero tiene el beneficio adicional de elegir el segundo valor más grande estrictamente más pequeño frente a múltiples valores altos (como 7
y 7
superiores).
Respuesta3
Es un buen trabajo para DC:
array=(1 2 7 6)
echo ${array[*]} | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'