Sortir jangan menyortir garis dengan pipa '|' di dalamnya dengan benar

17

Saya mencoba mengurutkan beberapa data sederhana yang dibatasi pipa. Namun, sort sebenarnya tidak menyortir. Ini memindahkan baris tajuk ke bawah, tetapi dua baris saya yang dimulai dengan 241 sedang dibagi dengan satu baris yang dimulai dengan 24.

cat sort_fail.csv
column_a|column_b|column_c
241|212|20810378
24|121|2810172
241|213|20810376

sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

Header kolom sedang dipindahkan ke bagian bawah file, jadi sortir sedang memprosesnya. Tapi, nilai sebenarnya tidak diurutkan seperti yang saya harapkan.

Dalam hal ini saya bekerja dengannya

sort sort_fail.csv --field-separator='|' -k1,1

Tapi, aku merasa itu seharusnya tidak perlu. Kenapa sort tidak menyortir?

pengguna10777668
sumber
2
gunakan LC_COLLATE=C sort. Bergantung pada apa yang Anda harapkan, Anda mungkin juga perluLC_COLLATE=C sort -t'|' -n
mosvy
3
Untuk mengurutkan "gaya csv" Data Anda mungkin ingin menggunakan csvsortdari csvkit, yang benar menangani nilai-nilai dikutip.
Bakuriu

Jawaban:

32

sort bersifat lokal, jadi tergantung pada pengaturan LC_COLLATE Anda (yang diwarisi dari LANG) Anda mungkin mendapatkan hasil yang berbeda:

$ LANG=C sort sort_fail.csv 
241|212|20810378
241|213|20810376
24|121|2810172
column_a|column_b|column_c

$ LANG=en_US sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

Ini dapat menyebabkan masalah dalam skrip, karena Anda mungkin tidak mengetahui apa yang diatur ke lokasi panggilan, dan karenanya mungkin mendapatkan hasil yang berbeda.

Bukan hal yang aneh bagi skrip untuk memaksakan pengaturan yang diperlukan

misalnya

$ grep 'LC.*sort' /bin/precat
      LC_COLLATE=C sort -u | prezip-bin -z "$cmd: $2"

Nah, yang menarik, di sini, |karakternya terlihat aneh.

Tapi itu karena aturan default untuk en_US, yang berasal dari ISO, kata

$ grep 007C /usr/share/i18n/locales/iso14651_t1_common
<U007C> IGNORE;IGNORE;IGNORE;<j> # 142 |

Yang berarti |karakter diabaikan dan urutannya akan seolah-olah karakter tidak ada ..

$ tr -d '|' < sort_fail.csv | LANG=C sort
24121220810378
241212810172
24121320810376
column_acolumn_bcolumn_c

Dan itu cocok dengan penyortiran "tak terduga" yang Anda lihat.

Pekerjaan di sekitar adalah menggunakan -n(untuk memaksa jenis numerik), atau menggunakan pemisah bidang (seperti yang Anda lakukan) atau menggunakan Clokal.

Stephen Harris
sumber
Menarik. Saya memang melihat beberapa hit lain tentang pelokalan, tetapi mengira itu akan berdampak pada pemesanan relatif 24 vs 241, bukan sesuatu seperti ini.
user10777668
7
sesuatu yang ekstra berguna dalam jenis GNU adalah --debugopsi, yang menunjukkan kunci (bergaris bawah) yang digunakan untuk membandingkan
Jeff Schaller
berjalan dengan --debug hanya menggarisbawahi seluruh baris - semacam termasuk karakter pipa, itu hanya diatur tidak memiliki dampak karena lokalisasi. Ini adalah fitur yang baik tetapi tidak membantu saya dalam kasus ini (saya mencoba :)
user10777668
Itulah mengapa saya menyebutkannya, @ user10777668 - ini menunjukkan bahwa sortmenggunakan seluruh baris alih-alih berhenti pada karakter yang kita asumsikan.
Jeff Schaller
Saya tidak berharap untuk berhenti. Saya mengharapkannya mengenali karakter pipa dan memasukkannya ke dalam jenis, oleh karena itu memperlakukan 24 | 1 dan 241 berbeda. Saya tidak yakin bagaimana - debug akan mengubah itu, dan bahkan mengingat bahwa itu menggarisbawahi | sepertinya itu akan secara aktif teralihkan dari masalah nyata di mana lokalisasi menyebabkan karakter pipa dimasuki
user10777668
1

Yang mengganggu saya adalah bahwa 24tidak bergerak dari tempatnya di antara keduanya 241. Kolom kedua dimulai dengan a 1. Mencoba mengurutkan dengan memimpin 4di bidang kedua, 24itu dipindahkan ke bawah, jadi saya curiga sortmengabaikan saja |kecuali diberitahu sebaliknya. Coba sort -n...

RudiC
sumber
1

-n, --numeric-sort membandingkan menurut nilai numerik string

210
23

Tanpa -n, 210 melalui teks berada di depan 23 seiring berjalannya karakter karakter saya.

michaelkrieger
sumber
Anda benar, tetapi ini tidak menjelaskan karakter pipa berbeda. Jawaban lain menunjukkan bahwa karena lokal, pipa diperlakukan sebagai tidak ada sehingga digit berikutnya adalah yang menentukan pemesanan.
Criggie