Làm thế nào để thực hiện sắp xếp tùy chỉnh bằng cách sử dụng sắp xếp unix?


11

Tôi đang sử dụng sắp xếp unix để sắp xếp một tệp được phân tách bằng dấu phẩy với nhiều cột. Cho đến nay, điều này đã làm việc hoàn hảo để sắp xếp dữ liệu theo số hoặc theo thứ tự bảng chữ cái:

Ví dụ tập tin trước khi sắp xếp:

C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

Sắp xếp tệp: $ sort -t ',' -k 2,2 -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Kết quả được sắp xếp:

A,Bahamas,Bahamas,Nassau,f,2
A,Canada,QC,Montreal,f,2
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1

Đây là vấn đề: Tôi muốn sắp xếp cột 2 dựa trên một loại tùy chỉnh, nghĩa là tôi muốn Hoa Kỳ trước, sau đó là Canada, sau đó là Bahamas:

Sắp xếp mong muốn:

A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

Có cách nào để vượt qua unix sắp xếp thứ tự tùy chỉnh mà sau đó nó có thể áp dụng không? Cái gì đó như: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Cảm ơn!


3
Đối với ba giá trị này, bạn muốn thứ tự chữ cái ngược. Đối với trường hợp chung, bạn sẽ cần ánh xạ tên thành số thứ tự sắp xếp và sau đó thực hiện sắp xếp bằng cách sử dụng số thứ tự sắp xếp. Hoặc sử dụng ngôn ngữ kịch bản ... Một khả năng là joinlệnh, nhưng bạn có thể sắp xếp rất nhiều thứ - các tệp đầu vào joinphải được sắp xếp theo một thứ tự, và sau đó bạn sẽ sử dụng sortlại để đưa dữ liệu vào một thứ tự khác (và mất cột thứ tự sắp xếp như một bước sau sắp xếp).
Jonathan Leffler

Trong ví dụ đầu vào của bạn, không nên có tthay vì ftrong dòng cuối cùng?
Lev Levitsky

Lev: vâng, bắt tốt. Lỗi của tôi; quá nhiều cắt và dán (bộ dữ liệu thực tế của tôi lớn hơn nhiều và tôi vô tình lấy nhầm hàng).

Tôi đã cập nhật câu trả lời để phù hợp với dữ liệu của bạn.
Lev Levitsky

Câu trả lời:


8

Câu trả lời và nhận xét khác trả lời câu hỏi nói chung, đây là cách triển khai có thể như sau:

$ cat order
Bahamas,3
Canada,2
United States,1

$ cat data
C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

$ sort -t, -k2 data | join -t, -11 -22 order - | sort -t, -k2n -k4,5 -k6r -k7nr | cut -d, -f 3,1,4-7
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

Tuyệt vời, cảm ơn sự giúp đỡ của bạn. Điều này làm việc hoàn hảo!

@jewelia Cải thiện một lần nữa, sedkhông thực sự cần thiết ở đây.
Lev Levitsky

1

Bạn không thể làm điều đó với sắp xếp . Tại thời điểm này, bạn thực sự nên đạt được awk / perl / ngôn ngữ bạn chọn . Bạn có thể fudge nó, mặc dù. Ví dụ, bạn có thể sử dụng sed để thay đổi "Hoa Kỳ" thành 0, "Canada" thành 1 và "Bahamas" thành 2, sau đó thực hiện sắp xếp số theo cột đó, sau đó quyến rũ lại. Hoặc thay đổi "Hoa Kỳ" thành "Hoa Kỳ, 0", v.v., sắp xếp theo cột thêm và sau đó loại bỏ nó.


0

Tôi chỉ viết một người trợ giúp gọi là csort để làm cho nó dễ dàng. Nó tiền tố mỗi dòng có giá trị bạn chọn dựa trên chuỗi con hoặc biểu thức chính quy khớp với dòng:

$ csort -t, '2=United States' X 2=Canada Y 2=Bahamas Z < tmp.csv | \
sort -t, -k1,1 -k3,3 -k4,4 -k5,5 -k6,6r -k7,7nr
X,A,United States,MA,Boston,f,0
X,B,United States,NY,New York,f,5
X,A,United States,NY,New York,f,1
X,C,United States,WA,Tacoma,f,1
Y,A,Canada,QC,Montreal,f,2
Z,A,Bahamas,Bahamas,Nassau,f,2

Các 2=STRphương tiện ký hiệu "trận đấu nếu trường thứ hai bằng STR".

Sau đó, bạn có thể tùy ý dẫn đầu ra thông qua cut -c3-để loại bỏ tiền tố.

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.