
Ich habe ein Array wie dieses:
array=(1 2 7 6)
und möchte nach dem zweitgrößten Wert suchen, wobei die Ausgabe lautet
secondGreatest=6
Gibt es eine Möglichkeit, dies in Bash zu tun?
Antwort1
printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1
Drucken Sie jeden Wert des Arrays in einer eigenen Zeile, sortieren Sie ihn, holen Sie sich die letzten beiden Werte und entfernen Sie den letzten Wert
secondGreatest=$(printf '%s\n' "${array[@]}" | sort -n | tail -2 | head -1)
Legen Sie diesen Wert für die secondGreatest
Variable fest.
Glenn Jackman hatte einen hervorragenden Punkt zu doppelten Zahlen, den ich nicht berücksichtigt habe. Wenn Sie nur an eindeutigen Werten interessiert sind, können Sie das -u
Flag of Sort verwenden:
secondGreatest=$(printf '%s\n' "${array[@]}" | sort -nu | tail -2 | head -1)
Antwort2
Eine bash-spezifische Schleife durch das Array könnte dies tun; Sie müssen den größten und den zweitgrößten Wert im Auge behalten. Der einzige andere schwierige Teil ist, beim Initialisieren dieser Werte vorsichtig zu sein; der größte Wert wird mit dem ersten Element initialisiert; der zweitgrößte Wert wird initialisiert, wenn wir zum ersten Mal einen Wert sehen, der kleiner als der größte Wert ist. Anschließend aktualisieren wir den zweitgrößten Wert nur, wenn er strikt kleiner als der aktuell größte Wert ist:
#!/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"
Dies ist immer noch langsamer als der Aufruf von , bietet aber den zusätzlichen Vorteil, dass bei mehreren hohen Werten (wie z. B. und höher) sort
der strikt kleinere zweitgrößte Wert ausgewählt wird .7
7
Antwort3
Es ist ein guter Job für dc:
array=(1 2 7 6)
echo ${array[*]} | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'