Sắp xếp nhiều khóa với sắp xếp Unix


137

Tôi có các tệp lớn có khả năng cần được sắp xếp theo các phím 1-n. Một số các phím này có thể là số và một số trong số chúng có thể không. Đây là một tệp cột có chiều rộng cố định nên không có dấu phân cách.

Có cách nào tốt để làm điều này với Unix sort không? Với một phím, nó đơn giản như sử dụng '-n'. Tôi đã đọc trang người đàn ông và tìm kiếm Google một thời gian ngắn, nhưng không tìm thấy một ví dụ hay. Làm thế nào tôi sẽ đi về việc hoàn thành điều này?

Lưu ý: Tôi đã loại trừ Perl vì tiềm năng kích thước tệp. Nó sẽ là một phương sách cuối cùng.


Một hoặc hai dòng dữ liệu mẫu sẽ thực sự hữu ích để tạo dòng lệnh mẫu. Ngoài ra, các phím "1-n" có nghĩa là bạn cần sắp xếp theo số lượng khóa khác nhau không? Làm điều đó mà không có kịch bản sẽ rất vui ...
Ken Gentle

Tôi có một trình bao bọc PHP xung quanh lệnh sort để kích hoạt tính năng 1-n.
Chris Kloberdanz

Câu trả lời:


69

Sử dụng -ktùy chọn (hoặc --key=POS1[,POS2]). Nó có thể xuất hiện nhiều lần và mỗi khóa có thể có các tùy chọn chung (chẳng hạn như nsắp xếp số)


7
Từ trang man sort: "POS là F [.C] [OPTS], trong đó F là số trường và C vị trí ký tự trong trường; cả hai đều là gốc 1." Xem trang người đàn ông để biết tài liệu đầy đủ.
Adam Rosenfield

49
Cũng xem câu trả lời của andras nếu bạn không muốn phát điên.
ron

1
Cả hai ý kiến ​​trên là chính xác và phụ gia. Cảm ơn các quý ông.
Ken Gentle

314

Hãy cẩn thận:

Nếu bạn muốn sắp xếp tệp chủ yếu theo trường 3 và thứ hai theo trường 2, bạn muốn điều này:

sort -k 3,3 -k 2,2 < inputfile

Không phải cái này: sort -k 3 -k 2 < inputfile sắp xếp tệp theo chuỗi từ đầu trường 3 đến cuối dòng (có khả năng là duy nhất).

-k, --key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2
                          (default end of line)

8
Thay đổi cuộc sống. Cảm ơn.
davidtbernal

2
Rất tiếc! Bây giờ tôi phải sửa một tập lệnh bởi vì trước đó tôi chỉ thấy câu trả lời đầu tiên ở trên ... điều tốt là tôi chưa phụ thuộc vào đầu ra của tập lệnh ....
Wildcard

Đẹp! Bây giờ, điều gì sẽ xảy ra nếu tôi muốn fleld 3 được sắp xếp theo số và ngược lại trong khi trường 2 không được sắp xếp theo số và bình thường (tăng dần)? :)
Arun

2
@Arun POS được giải thích ở cuối trang man. Bạn chỉ cần nối các tùy chọn đặt hàng vào số trường như thế này:sort -k 3,3nr -k 2,2
andras

1
Aargh. Thật là một giao diện phản trực giác: -k2nên là -k2,2một dấu phẩy kéo dài -k2,phải là 'kết thúc mặc định kỳ diệu của dòng hoặc bất cứ thứ gì'.
android.weasel

94

Tùy chọn -k là những gì bạn muốn.

-k 1.4,1.5n -k 1.14,1.15n

Sẽ sử dụng các vị trí ký tự 4-5 trong trường đầu tiên (tất cả là một trường cho chiều rộng cố định) và sắp xếp số lượng làm khóa đầu tiên.

Khóa thứ hai cũng sẽ là các ký tự 14-15 trong trường đầu tiên.

(biên tập)

Ví dụ (tất cả những gì tôi có là DOS / cygwin tiện dụng):

dir | \cygwin\bin\sort.exe -k 1.4,1.5n -k 1.40,1.60r

cho dữ liệu:

12/10/2008  01:10 PM         1,564,990 outfile.txt

Sắp xếp danh sách thư mục theo số tháng (pos 4-5) theo số và sau đó theo tên tệp (pos 40-60) theo chiều ngược lại. Vì không có tab, nên tất cả là trường 1 để sắp xếp.


Nó chỉ là một trường nếu không có khoảng trống trong dữ liệu đầu vào. Tuy nhiên, ví dụ của bạn là hữu ích.
Jonathan Leffler

Sửa chữa: nếu không có / tab / trong dữ liệu đầu vào. Trong đầu ra lệnh 'dir' của DOS, không có tab nào.
Clinton Pierce

Các ví dụ về cách sử dụng các tùy chọn (số, đảo ngược) cực kỳ hữu ích, vì gần như không thể tìm ra cách sử dụng chỉ từ trang man và các câu trả lời khác không đề cập đến. Tôi ước tôi có thể +2 cho việc này. ;)
msb

22

Đây là một để sắp xếp các cột khác nhau trong tệp csv theo thứ tự số và từ điển, cột 5 và sau là thứ tự từ điển

~/test>sort -t, -k1,1n -k2,2n -k3,3d -k4,4n -k5d  sort.csv
1,10,b,22,Ga
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C

~/test>cat sort.csv
2,3,a,9,C
2,2,b,20,F
2,2,c,19,Gb,hj
2,2,c,19,Gb,hi
2,2,c,19,Ga
2,2,b,22,Ga
1,10,b,22,Ga

Lưu ý -k1,1n có nghĩa là số bắt đầu từ cột 1 và kết thúc ở cột 1. Nếu tôi đã thực hiện bên dưới, nó sẽ nối liền cột 1 và 2, tạo thành 1,10 được sắp xếp thành 110

~/test>sort -t, -k1,2n -k3,3 -k4,4n -k5d  sort.csv
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C
1,10,b,22,Ga

1
Đây là câu trả lời tốt nhất vì nó cho thấy cách sử dụng các công tắc khác nhau cho các cột khác nhau
xaxa

12

Tôi tin vào trường hợp của bạn

sort -t@ -k1.1,1.4 -k1.5,1.7 ... <inputfile

sẽ làm việc tốt hơn @ là dấu phân cách trường, hãy chắc chắn rằng đó là một ký tự không xuất hiện. sau đó đầu vào của bạn được coi là bao gồm một cột.

Chỉnh sửa: rõ ràng clintp đã đưa ra một câu trả lời tương tự, xin lỗi. Như ông chỉ ra, các cờ 'n' và 'r' có thể được thêm vào mỗi tùy chọn -k ....


Mặc dù dấu phân cách mặc định liên quan đến tài liệu gnu.org/software/coreutils/manual/html_node/, là không gian, đôi khi số lượng trường không như bạn mong đợi. Có lẽ như những người khác đã nói ở đây vì cài đặt ngôn ngữ LC_CTYPE. Khi nghi ngờ tính từ đầu dòng!
Brad Dre

5

Lưu ý rằng cũng có thể mong muốn ổn định sắp xếp với công -stắc, để các dòng được xếp hạng bằng nhau duy trì thứ tự tương đối ban đầu của chúng trong đầu ra.


2

Tôi chỉ muốn thêm một số mẹo, khi bạn sử dụng sort, hãy cẩn thận về ngôn ngữ của bạn có ảnh hưởng đến thứ tự so sánh khóa. Tôi thường sử dụng rõ ràng LC_ALL = C để tạo miền địa phương những gì tôi muốn.


LC_ALL = C cũng có thể dẫn đến tăng tốc khá!
mat kelcey
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.