GNU sort sort sort ổn định khi sort không biết thứ tự sắp xếp


18

Tôi có một tệp hai cột; tập tin được sắp xếp theo cách tôi muốn trên cột 1. Tôi muốn sắp xếp trên cột 2, trong mỗi loại 1 cột. Tuy nhiên, sortkhông hiểu thứ tự sắp xếp của cột 1.

Cách thông thường (từ các câu hỏi tương tự ở đây trên stack) sẽ là:

sort --stable -k1,1 -k2,2n

Nhưng tôi không thể chỉ định sắp xếp trên k1, vì nó là tùy ý.

Ví dụ đầu vào:

C 2
C 1
A 2
A 1
B 2 
B 1

và đầu ra:

C 1
C 2
A 1
A 2
B 1 
B 2

Câu trả lời:


20

Bạn có thể sử dụng awk để bắt đầu một loại mới cho mỗi khối:

% awk -v cmd="sort -k2,2" '$1 != prev {close(cmd); prev=$1} {print | cmd}' foo
C 1
C 2
A 1
A 2
B 1
B 2
  • $1 != prev {close(cmd); prev=$1} - khi giá trị lưu khác nhau, chúng tôi có một khối mới, vì vậy chúng tôi đóng bất kỳ bắt đầu nào trước đó sort
  • {print | "sort -k2,2"}'dẫn đầu ra đến sort, khởi động nó nếu nó chưa chạy (awk có thể theo dõi các lệnh mà nó bắt đầu)

2
awk thực sự đáng kinh ngạc Tôi thích điều này nhiều hơn những gì tôi mong đợi, đó là một cách trang trí tuyệt vời!
Evan Benn

Tôi đã cố gắng so sánh sự hoàn hảo của câu hỏi này với câu trả lời khác, không chắc tại sao cái này sử dụng nhiều tài nguyên hơn ... Có ý tưởng nào không? gist.github.com/EvanTheB/5b64eafb84eeaf51c289295ac06e1b0b
Evan Benn

Bạn đã chạy trung bình bao nhiêu lần?
muru

Tôi đã không tính trung bình, nhưng tôi thấy thời gian chạy ổn định khi tôi lặp lại và điều tra.
Evan Benn

Đây là một tệp tương tự với những gì tôi đang sử dụng nếu bạn muốn điều tra:seq 30 | xargs -L1 bash -cs 'yes $1 | head -1000000 | paste - <(seq 1000000) | shuf' bash
Evan Benn

12

Bạn có thể sử dụng một biến đổi Schwartzian (về cơ bản đây là cách tiếp cận không sắp xếp trang trí mà bạn đã đề cập trong một nhận xét, nhưng có khả năng thực hiện nhiều hơn câu trả lời tốt của muru do sử dụng một lời gọi duy nhất thay vì nhiều lần) - sử dụng thêm một cột tiền tố gia tăng với sự thay đổi giá trị trong cột đầu tiên, sắp xếp theo cột tiền tố theo sau là cột "thứ hai" (vị trí thứ tự đã tạm thời chuyển sang do sự hiện diện của cột tiền tố) và cuối cùng thoát khỏi cột tiền tốsortawk3

awk '{print ($1 in a? c+0: ++c)"\t" $0; a[$1]}' file | sort -k1,1n  -k3,3 | cut -f 2-

Tôi ngạc nhiên, nhưng bạn đã đúng, điều này nhanh hơn câu trả lời khác! 3 phút so với 2 phút trên tệp dòng 100 triệu của tôi (~ 30 cột đầu tiên).
Evan Benn

1
Không cần phải giữ một mảng của khóa duy nhất từ ​​cột đầu tiên. Tôi nghĩ rằng nó là đủ để so sánh cột đầu tiên của dòng hiện tại với cột trước đó.
Kusalananda

Một cái gì đó như awk -v OFS="\t" '$1 != prev { key++ } { print key, $0; prev = $1 }(chưa được kiểm tra).
Kusalananda
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.