Wie kann ich eine Liste mit der Ebene major.minor.patch und manchmal rc richtig sortieren?


18

Ich muss die folgende Liste mit einem Shell-Skript sortieren und die neueste Version oben oder unten anzeigen. Wie würde ich das nur mit Shell-Tools machen?

release-5.0.0.rc1
release-5.0.0.rc2
release-5.0.0
release-5.0.1
release-5.0.10
release-5.0.11
release-5.0.13
release-5.0.14
release-5.0.15
release-5.0.16
release-5.0.17
release-5.0.18
release-5.0.19
release-5.0.2
release-5.0.20
release-5.0.21
release-5.0.22
release-5.0.23
release-5.0.24
release-5.0.25
release-5.0.26
release-5.0.27
release-5.0.28
release-5.0.29
release-5.0.3

1
Siehe auch printf '%s\n' ${(on)array}in zsh. (Wenn sich die Liste im $arrayArray befindet).
Stéphane Chazelas

Antworten:


20

GNU sort hat, -Vdass meistens mit einer Liste wie dieser umgehen kann ( Details ):

 -V, --version-sort
        natural sort of (version) numbers within text

$ cat vers
release-5.0.19
release-5.0.19~pre1
release-5.0.19-bigbugfix
release-5.0.2
release-5.0.20
$ sort -V vers
release-5.0.2
release-5.0.19~pre1
release-5.0.19
release-5.0.19-bigbugfix
release-5.0.20

Diese .rc*Versionen könnten jedoch ein kleines Problem darstellen, da sie wahrscheinlich vor der entsprechenden Nicht-RC-Version sortiert werden sollten , wenn es also zufällig beides gibt. Einige Versionsverwaltungssysteme (wie Debian) verwenden Suffixe, die mit tilde ( ~) beginnen, um Vorabversionen zu kennzeichnen, und sortieren vor der Version ohne Suffix, die vor Versionen mit anderen Suffixen sortiert wird. Anscheinend wird dies zumindest sortvon meinem System unterstützt, wie oben gezeigt ( sort (GNU coreutils) 8.23).


3
Sniped mich um ein paar Sekunden :)
Rosuav

1
Vielen Dank. Habe mir nicht einmal vorgestellt, dass diese Sorte eine solche Option haben würde.
Mandragor

FWIW, -Vwird standardmäßig auch sortunter OpenBSD unterstützt, jedoch nicht unter NetBSD.
Kusalananda

Auch FreeBSD hat anscheinend eine Manpage mit einer Beispielausgabereihenfolge, die mit der OpenBSD identisch ist.
Ilkkachu

7

Auschecken sort -V:

   -V, --version-sort
          natural sort of (version) numbers within text

Versionsnummern sind komplizierte Biester, mit sehr wenigen Standards, die die alphabetischen Teile regeln, aber probieren Sie dies an Ihren tatsächlichen Daten aus und prüfen Sie, ob es ausreicht.


Wow großartig! Dies funktioniert sogar für ein altes Problem mit Dateinamen mayorNumber–minorNumer some text, bei dem die Feldsortierung aufgrund eines Unicode-Trennzeichens fehlschlägt. Danke für den Hinweis!
Philippos

3

Dies kann als eine Zeile erfolgen, wird hier jedoch aus Gründen der Lesbarkeit in mehrere Zeilen (an den Pipes) aufgeteilt und behandelt auch die rc.

Wenn Sie keine -VOption für Ihre Sortierung haben oder auch wenn Sie dies tun, müssen Sie sich mit den folgenden Situationen befassen rc:

cat versionlist |
sed -e "s/release-//" -e "s/rc//" |
sort -t. -n -k1,1 -k2,2 -k3,3 -k4,4 |
sed -r -e "s/([^.]+)\.([^.]+)\.([^.]+)\.([^.]+)/\1.\2.\3.rc\4/" -e "s/^/release-/"

Das erste entfernt seddie nicht-numerischen Zeichen.
Das sortverwendet ein .Trennzeichen ( -t.), eine numerische Sortierung (- n) und Tasten ( -k).
Das letzte sedsetzt die nicht-numerischen Zeichen zurück.


0

Vielen Dank für all die Inspiration - Darf ich meine eigene Antwort vorschlagen: Das Sortierprogramm kann dazu verleitet werden, das zu tun, was benötigt wird. Am Ende geht es darum, der dreistelligen Versionierung eine vierte Zahl hinzuzufügen, sie zu sortieren und dann wieder zu entfernen. Funktioniert - bisher einfachste Lösung, IMHO.

cat versionlist |\
sed -r "s/([0-9]+\.[0-9]+\.[0-9]+$)/\1\.99999/"|sort -V|sed s/\.99999$//

Ergebnis:

release-5.0.0.rc1
release-5.0.0.rc2
release-5.0.0

....

0
$ cat /tmp/tmp.tmp
release-5.0.0.rc1
release-5.0.0.rc2
release-5.0.0
release-5.0.1
release-5.0.10
release-5.0.11
release-5.0.13
release-5.0.14
release-5.0.15
release-5.0.16
release-5.0.17
release-5.0.18
release-5.0.19
release-5.0.2
release-5.0.20
release-5.0.21
release-5.0.22
release-5.0.23
release-5.0.24
release-5.0.25
release-5.0.26
release-5.0.27
release-5.0.28
release-5.0.29
release-5.0.3

$ cat /tmp/tmp.tmp | awk -F\- '{ print $2,$1 }' | sort -n | awk '{ print $2 "-" $1 }'
release-5.0.0
release-5.0.0.rc1
release-5.0.0.rc2
release-5.0.1
release-5.0.10
release-5.0.11
release-5.0.13
release-5.0.14
release-5.0.15
release-5.0.16
release-5.0.17
release-5.0.18
release-5.0.19
release-5.0.2
release-5.0.20
release-5.0.21
release-5.0.22
release-5.0.23
release-5.0.24
release-5.0.25
release-5.0.26
release-5.0.27
release-5.0.28
release-5.0.29
release-5.0.3

$

release-5.0.0 sollte NACH .rc1 und .rc2 in der Liste erscheinen. das ist hier die herausforderung.
Mandragor
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.