Sắp xếp không sắp xếp các dòng với một đường ống '|' trong đó một cách chính xác


17

Tôi đang cố gắng sắp xếp một số dữ liệu phân định đường ống đơn giản. Tuy nhiên, sắp xếp không thực sự sắp xếp. Nó di chuyển hàng tiêu đề của tôi xuống dưới cùng, nhưng hai hàng của tôi bắt đầu bằng 241 đang bị chia tách bởi một hàng bắt đầu bằng 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

Các tiêu đề cột đang được di chuyển xuống dưới cùng của tệp, vì vậy sắp xếp rõ ràng là xử lý nó. Nhưng, các giá trị thực tế không được sắp xếp như tôi mong đợi.

Trong trường hợp này tôi đã làm việc xung quanh nó với

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

Nhưng, tôi cảm thấy như thế là không cần thiết. Tại sao sắp xếp không sắp xếp?


2
sử dụng LC_COLLATE=C sort. Tùy thuộc vào những gì bạn đang mong đợi, bạn cũng có thể cầnLC_COLLATE=C sort -t'|' -n
mosvy 11/12/18

3
Để sắp xếp "phong cách csv" dữ liệu bạn có thể muốn sử dụng csvsorttừ csvkit, mà đúng handle giá trị niêm yết.
Bakuriu

Câu trả lời:


32

sort là nhận thức địa phương, do đó tùy thuộc vào cài đặt LC_COLLATE của bạn (được kế thừa từ LANG), bạn có thể nhận được các kết quả khác nhau:

$ 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

Điều này có thể gây ra sự cố trong tập lệnh, bởi vì bạn có thể không nhận thức được địa điểm cuộc gọi được đặt thành gì và do đó có thể nhận được các kết quả khác nhau.

Không có gì lạ khi các tập lệnh buộc cài đặt cần thiết

ví dụ

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

Bây giờ điều thú vị ở đây là |nhân vật có vẻ kỳ quặc.

Nhưng đó là vì quy tắc mặc định cho en_US, xuất phát từ ISO, nói

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

Điều đó có nghĩa là |nhân vật bị bỏ qua và thứ tự sắp xếp sẽ như thể nhân vật không tồn tại ..

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

Và nó phù hợp với cách sắp xếp "bất ngờ" mà bạn đang thấy.

Các công việc xung quanh là sử dụng -n(để buộc các loại số) hoặc sử dụng dấu tách trường (như bạn đã làm) hoặc sử dụng Cmiền địa phương.


Hấp dẫn. Tôi đã thấy một số lượt truy cập khác về nội địa hóa, nhưng hình dung rằng nó sẽ ảnh hưởng đến thứ tự tương đối 24 so với 241, không phải như thế này.
user10777668

7
một cái gì đó hữu ích hơn trong sắp xếp GNU là --debugtùy chọn, cho biết khóa (gạch chân) được sử dụng để so sánh
Jeff Schaller

chạy với --debug chỉ gạch chân toàn bộ dòng - sắp xếp bao gồm ký tự ống, nó chỉ được đặt là không có tác động vì nội địa hóa. Đây là một tính năng tốt nhưng không giúp tôi trong trường hợp này (tôi đã thử :)
user10777668

Đó chính xác là lý do tại sao tôi đã đề cập đến nó, @ user10777668 - nó chỉ ra rằng sortđang sử dụng toàn bộ dòng thay vì dừng lại ở các ký tự mà chúng ta cho là như vậy.
Jeff Schaller

Tôi đã không mong đợi nó dừng lại. Tôi đã mong đợi nó nhận ra ký tự ống và bao gồm nó trong loại, do đó xử lý 24 | 1 và 241 khác nhau. Tôi không chắc chắn làm thế nào --debug đã thay đổi điều đó, và trên thực tế cho rằng nó gạch chân | có vẻ như nó đã chủ động phân tâm khỏi vấn đề thực sự trong đó việc bản địa hóa dẫn đến nhân vật tẩu đang được sử dụng
user10777668

1

Điều làm tôi khó chịu là việc 24không di chuyển từ vị trí của nó giữa hai người 241. Trường thứ hai bắt đầu bằng a 1. Cố gắng sắp xếp với một người dẫn đầu 4trong lĩnh vực thứ hai, việc 24này được chuyển xuống, vì vậy tôi nghi ngờ sortchỉ cần bỏ qua |trừ khi được nói khác đi. Hãy thử sort -n...


1

-n, --numeric-sort so sánh theo giá trị số chuỗi

210
23

Không có -n, 210 bằng văn bản đi trước 23 vì nó đi vào nhân vật của tôi.


Bạn nói đúng, nhưng điều này không giải thích ống char là khác nhau. Các câu trả lời khác cho thấy vì địa phương, đường ống được coi là không có nên chữ số tiếp theo là thứ quyết định thứ tự.
Criggie
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.