Come posso ordinare un elenco con il livello major.minor.patch e talvolta rc correttamente?


18

Devo ordinare il seguente elenco con uno script di shell e far apparire l'ultima versione in basso o in alto. Come lo farei solo con gli strumenti shell?

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
Vedi anche printf '%s\n' ${(on)array}in zsh. (quando l'elenco è nella $arraymatrice).
Stéphane Chazelas

Risposte:


20

L'ordinamento GNU ha -Vche può principalmente gestire un elenco del genere ( dettagli ):

 -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

Tuttavia, quelle .rc*versioni potrebbero essere un po 'un problema, dal momento che probabilmente dovrebbero essere ordinate prima della corrispondente versione non rc, se ci sono state entrambe, cioè. Alcuni sistemi di controllo delle versioni (come Debian), usano i suffissi che iniziano con una tilde ( ~) per contrassegnare le pre-release, e ordinano prima della versione senza un suffisso, che ordina le versioni precedenti con altri suffissi. Apparentemente questo è supportato da almeno sortsul mio sistema, come mostrato sopra ( sort (GNU coreutils) 8.23).


3
Mi ha colpito di un paio di secondi :)
rosuav

1
Molte grazie. Non immaginavo nemmeno che quel tipo avrebbe avuto un'opzione del genere.
Mandragor

FWIW, -Vsupportato anche di default sortsu OpenBSD, ma non su NetBSD.
Kusalananda

Anche FreeBSD, a quanto pare , la pagina man lì ha anche un esempio di output e sembra identica a quella di OpenBSD.
Ilkkachu,

7

Dai un'occhiata sort -V:

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

I numeri di versione sono bestie complicate, con pochissimi standard che governano le porzioni alfabetiche, ma prova questo sui tuoi dati reali e vedi se è sufficiente.


Wow grande! Questo funziona anche per un mio vecchio problema con i nomi dei file mayorNumber–minorNumer some text, in cui l'ordinamento dei campi non riesce a causa del delimitatore unicode. Grazie per il suggerimento!
Philippos,

3

Questo può essere fatto come una riga, ma diviso in più righe (ai tubi) qui per leggibilità, e gestisce rcanche quello.

Se non hai -Vun'opzione per il tuo ordinamento, o anche se lo fai, dovrai occuparti di occasionali 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-/"

Le prime sedstrisce i caratteri non numerici
le sortutilizza un .delimitatore ( -t.), ordinamento numerico (- n), e tasti ( -k)
le finali sedmette i caratteri non numerici in posizione.


0

Grazie per tutta l'ispirazione - Posso proporre la mia risposta: il programma di ordinamento può essere indotto a fare ciò che è necessario. Alla fine si tratta di aggiungere un quarto numero al versioning a 3 cifre, ordinarlo e quindi rimuoverlo di nuovo. Funziona - la soluzione più semplice finora, IMHO.

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

risultato:

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

$

la versione 5.0.0 dovrebbe venire DOPO .rc1 e .rc2 nell'elenco. questa è la sfida qui.
Mandragor
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.