Bagaimana cara mengurutkan string yang dikombinasikan dengan string + numerik menggunakan skrip bash?

27

Ini adalah data yang ingin saya urutkan. Tetapi sortmemperlakukan numerik menjadi string, data itu tidak diurutkan seperti yang saya harapkan.

/ home / files / profile1
/ home / files / profile10
/ home / files / profile11
/ home / files / profile12
/ home / files / profile14
/ home / files / profile15
/ home / files / profile16
/ home / files / profile2
/ home / files / profile3
/ home / files / profile4
/ home / files / profile5
/ home / files6
/ home / files / profile7
/ home / files / profile8
/ home / files / profile9

Saya ingin menyortir ini,

/ home / files / profile1
/ home / files / profile2
/ home / files / profile3
/ home / files / profile4
/ home / files / profile5
/ home / files / profile6
/ home / files / profile7
/ home / files / profile8
/ home / files / profile9
/ home / files / profile10
/ home / files / profile11
/ home / files / profile12
/ home / files / profile14
/ home / files / profile15
/ home / files / profile16

Apakah ada cara yang baik dengan skrip bash? Saya tidak dapat menggunakan skrip ruby ​​atau python di sini.

pengguna760548
sumber
coba gunakan "sort -nd"
bobah
1
@ Bob, "sort: options` -dn 'tidak kompatibel "
maxschlepzig
10
sort -Vakan lakukan.
Thor
2
@Tor. komentar Anda akan menjadi jawaban yang bagus
Peter.O
stackoverflow.com/questions/13088370/sort-numerically
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

21

Anda dapat menggunakan karakter sementara untuk membatasi nomor:

$ sed 's/\([0-9]\)/;\1/' log | sort -n -t\; -k2,2 | tr -d ';'

Di sini, karakter penjaga adalah ';' - itu tidak boleh menjadi bagian dari nama file yang ingin Anda urutkan - tetapi Anda dapat menukar ';' dengan karakter apa pun yang Anda suka. Anda harus mengubah sed, sortdan trberpisah kemudian.

Pipa berfungsi sebagai berikut: sedPerintah menyisipkan sentinel sebelum nomor apa pun, sortperintah menafsirkan sentinel sebagai pembatas bidang, mengurutkan dengan bidang kedua sebagai kunci pengurutan numerik dan trperintah menghilangkan sentinel lagi.

Dan logmenunjukkan file input - Anda juga dapat memasukkan input Anda ke sed.

maxschlepzig
sumber
Saya suka cara Anda menyelesaikan masalah :)
SHW
44

Ini sangat mirip dengan pertanyaan ini . Masalahnya adalah bahwa Anda memiliki bidang alfanumerik yang sedang Anda sortir, dan -ntidak memperlakukannya dengan masuk akal, namun versi sortir ( -V) tidak. Jadi gunakan:

sort -V

Perhatikan bahwa fitur ini saat ini didukung oleh implementasi semacam GNU, FreeBSD dan OpenBSD.

Thor
sumber
Apakah Anda tahu seberapa portabel ini? Opsi ini tampaknya tidak menjadi bagian dari spesifikasi POSIX.
Ernest A
@ ErnestA: Anda benar, ini adalah solusi spesifik semacam GNU. Menambahkan catatan.
Thor
@ErnestA: Sepertinya FreeBSD dan OpenBSD telah menambahkan fitur ini.
Thor
Dan itu tidak berfungsi jika angkanya memiliki awalan yang berbeda.
Dante
1
Untuk setiap pembaca: Perhatikan bahwa ini adalah MODAL V! Gunakan sort -Vtidak sort -v. Sulit untuk mengatakan pada pandangan pertama.
Gabriel Staples
7

Jika semua nama file Anda memiliki awalan yang sama sebelum bagian numerik akhir, abaikan saja saat menyortir:

sort -k 1.20n

(20 adalah posisi digit pertama. Satu ditambah panjang /home/files/profile.)

Jika Anda memiliki beberapa bagian non-numerik yang berbeda, masukkan sentinel .

Gilles 'SANGAT berhenti menjadi jahat'
sumber