Bagaimana saya bisa mengurutkan daftar dengan tingkat major.minor.patch dan kadang-kadang rc dengan benar?


18

Saya harus mengurutkan daftar berikut dengan skrip shell dan membuat versi terbaru muncul di bagian bawah atau atas. Bagaimana saya melakukannya dengan alat shell saja?

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
Lihat juga printf '%s\n' ${(on)array}di zsh. (ketika daftar ada dalam $arrayarray).
Stéphane Chazelas

Jawaban:


20

Jenis GNU memiliki -Vyang sebagian besar dapat menangani daftar seperti itu ( perincian ):

 -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

Namun, .rc*versi - versi itu bisa menjadi sedikit masalah, karena mereka mungkin harus diurutkan sebelum versi non-rc yang sesuai, jika kebetulan keduanya, yaitu. Beberapa sistem versi (seperti Debian), menggunakan sufiks yang dimulai dengan tilde ( ~) untuk menandai pra-rilis, dan mereka mengurutkan sebelum versi tanpa sufiks, yang mengurutkan versi sebelum dengan sufiks lainnya. Rupanya ini didukung oleh setidaknya sortpada sistem saya, seperti yang ditunjukkan di atas ( sort (GNU coreutils) 8.23).


3
Mengecamku beberapa detik :)
rosuav

1
Terima kasih banyak. Bahkan tidak menyangka bahwa semacam itu akan memiliki opsi seperti itu.
Mandragor

FWIW, -Vjuga didukung secara default sortpada OpenBSD, tetapi tidak pada NetBSD.
Kusalananda

FreeBSD juga, tampaknya , halaman manual di sana juga memiliki contoh urutan output, dan terlihat identik dengan yang OpenBSD.
ilkkachu

7

Lihat sort -V:

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

Nomor versi adalah binatang yang rumit, dengan sangat sedikit standar yang mengatur bagian-bagian alfabet, tetapi coba ini pada data aktual Anda dan lihat apakah itu cukup.


Wow LUAR BIASA! Ini berfungsi bahkan untuk masalah lama saya dengan nama file mayorNumber–minorNumer some text, di mana pengurutan bidang gagal karena pembatas unicode. Terima kasih atas petunjuknya!
Philippos

3

Ini dapat dilakukan sebagai satu baris, tetapi dipecah menjadi beberapa baris (di pipa) di sini untuk dibaca, dan menangani rcjuga.

Jika Anda tidak memiliki -Vpilihan untuk jenis Anda, atau bahkan jika Anda punya, Anda harus berurusan dengan sesekali 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-/"

sedStrip pertama menghilangkan karakter non-numerik
. sortMenggunakan .pembatas ( -t.), sortir numerik (- n), dan kunci ( -k)
. Final sedmengembalikan karakter non-numerik kembali ke tempatnya.


0

Terima kasih atas semua inspirasi - Boleh saya mengusulkan jawaban saya sendiri: Program semacam ini bisa diakali untuk melakukan apa yang dibutuhkan. Pada akhirnya ini adalah tentang menambahkan angka keempat ke versi 3 digit, mengurutkannya, dan kemudian menghapusnya lagi. Bekerja - solusi paling sederhana sejauh ini, IMHO.

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

hasil:

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

$

rilis-5.0.0 harus datang SETELAH .rc1 dan .rc2 dalam daftar. itulah tantangannya di sini.
Mandragor
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.