Sự khác biệt giữa loại Sắp xếp -u và loại Sắp xếp | uniq?


120

Ở mọi nơi tôi thấy ai đó cần để có được một danh sách độc đáo, được sắp xếp, họ luôn luôn hướng đến sort | uniq. Tôi chưa bao giờ thấy bất kỳ ví dụ nào mà ai đó sử dụng sort -uthay thế. Tại sao không? Sự khác biệt là gì và tại sao sử dụng uniq tốt hơn so với cờ duy nhất để sắp xếp?


Câu trả lời:


120

sort | uniqđã tồn tại trước đây sort -uvà tương thích với nhiều hệ thống khác nhau, mặc dù hầu hết tất cả các hệ thống hiện đại đều hỗ trợ -u- đó là POSIX. Đó chủ yếu là sự trở lại cho đến ngày sort -ukhông tồn tại (và mọi người không có xu hướng thay đổi phương pháp của họ nếu cách mà họ biết vẫn tiếp tục hoạt động, chỉ cần nhìn vào ifconfigso với ipviệc áp dụng).

Cả hai có khả năng được hợp nhất vì loại bỏ trùng lặp trong một tệp yêu cầu sắp xếp (ít nhất là trong trường hợp tiêu chuẩn) và là trường hợp sử dụng cực kỳ phổ biến. Nó cũng nhanh hơn trong nội bộ do có thể thực hiện cả hai hoạt động cùng một lúc (và do thực tế là nó không yêu cầu IPC giữa uniqsort). Đặc biệt nếu tệp lớn, sort -ucó thể sẽ sử dụng ít tệp trung gian hơn để sắp xếp dữ liệu.

Trên hệ thống của tôi, tôi luôn nhận được kết quả như thế này:

$ dd if=/dev/urandom of=/dev/shm/file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 8.95208 s, 11.7 MB/s
$ time sort -u /dev/shm/file >/dev/null

real        0m0.500s
user        0m0.767s
sys         0m0.167s
$ time sort /dev/shm/file | uniq >/dev/null

real        0m0.772s
user        0m1.137s
sys         0m0.273s

Nó cũng không che giấu mã trở lại của sort, có thể là quan trọng (trong vỏ hiện đại có nhiều cách để có được điều này, ví dụ, bash's $PIPESTATUSmảng, nhưng điều này không phải luôn luôn đúng).


31
Tôi có xu hướng sử dụng sort | uniqvì 9 lần trong số 10, tôi thực sự đang chuyển sang uniq -c.
Plutor

5
Lưu ý rằng đó sort -ulà một phần của UNIX phiên bản thứ 7, khoảng năm 1979. Các phiên bản sortkhông có hỗ trợ -uthực sự là cổ xưa - hoặc được viết mà không chú ý đến tiêu chuẩn thực tế trước tiêu chuẩn de POSure của POSIX. Xem thêm Stack Overflow Sort & uniq trong Linux shell từ năm 2010
Jonathan Leffler

3
+1 vì ip. Đó là năm 2016 và bài đăng này vào năm 2013, nhưng tôi chỉ biết về iplệnh bây giờ.
chết

4
+1 cho "9 lần trên 10 Tôi thực sự chuyển sang uniq -c" (và có thể đường ống một lần nữa đến sort -nr | head). Tôi đã tự hỏi những gì tương đương với sort | uniqtrong Vim khi tôi phát hiện ra rằng Vim có :sort ulệnh. Và TIL sort -utồn tại là tốt.
Zhuoyun Wei

Lưu ý rằng có một sự khác biệt khi sử dụng sort -n | uniqso với sort -n -u. Ví dụ, dấu vết và khoảng trắng hàng đầu sẽ được xem là trùng lặp bởi sort -n -unhưng không phải bởi trước đây! echo -e 'test \n test' | sort -n -utrả về test, nhưng echo -e 'test \n test' | sort -n | uniqtrả về cả hai dòng.
mxmlnkn

46

Một điểm khác biệt là uniqcó một số tùy chọn bổ sung hữu ích, chẳng hạn như bỏ qua các trường để so sánh và đếm số lần lặp lại của một giá trị. sort's -ucờ chỉ thực hiện các chức năng của không trang trí uniqlệnh.


3
+0,49 cho một câu trả lời hữu ích, nhưng tôi sẽ diễn đạt nó như "Đầu ra của sort -ukhông thể được chuyển qua uniqđể sử dụng một số tùy chọn hữu ích sau này, chẳng hạn như bỏ qua các trường để so sánh và đếm số lần lặp lại."
l0b0

15
+1 để bù đắp cho những người không tán thành vì "không có cách nào để thực hiện điều này trực tiếp từ sắp xếp" sẽ trả lời câu hỏi ...
Izkata

42

Với các sorts và s tuân thủ POSIX uniq(GNU uniqhiện không tuân thủ về vấn đề đó), có một sự khác biệt trong đó sortsử dụng thuật toán đối chiếu của miền địa phương để so sánh các chuỗi (thường sẽ sử dụng strcoll()để so sánh các chuỗi) trong khi uniqkiểm tra nhận dạng giá trị byte (thường sẽ sử dụng strcmp()) .

Điều đó quan trọng vì ít nhất hai lý do.

  • Ở một số địa phương, đặc biệt là trên các hệ thống GNU, có các ký tự khác nhau sắp xếp giống nhau. Chẳng hạn, trong miền địa phương en_US.UTF-8 trên hệ thống GNU, tất cả các ký tự ①②③④⑤⑥⑦⑧⑨⑩ ... và nhiều ký tự khác sắp xếp giống nhau vì thứ tự sắp xếp của chúng không được xác định. Các chữ số Ả Rập 0123456789 sắp xếp giống như các đối tác Đông Ả Rập (٠١٢٣٤٥٦٧٨٩).

    sort -u, ① sắp xếp giống như và 0123 giống như ٠١٢٣ nên sort -usẽ chỉ giữ lại một trong số đó, trong khi đối với uniq(không phải GNU uniqsử dụng strcoll()(ngoại trừ -i)), khác với và 0123 khác với, vì vậy uniqsẽ xem xét tất cả 4 độc đáo.

  • strcollchỉ có thể so sánh các chuỗi ký tự hợp lệ (hành vi không được xác định theo POSIX khi đầu vào có các chuỗi byte không tạo thành các ký tự hợp lệ) trong khi strcmp()không quan tâm đến các ký tự vì nó chỉ thực hiện so sánh byte với byte. Vì vậy, đó là một lý do khác tại sao sort -ucó thể không cung cấp cho bạn tất cả các dòng duy nhất nếu một số trong số chúng không tạo thành văn bản hợp lệ. sort|uniq, trong khi vẫn chưa được chỉ định trên đầu vào không phải là văn bản, trong thực tế có nhiều khả năng cung cấp cho bạn các dòng duy nhất vì lý do đó.

Bên cạnh những sự tinh tế, có một điều mà chưa được ghi nhận cho đến nay là uniqso sánh toàn bộ dòng nghĩa từ vựng, trong khi sort's -urồi so sánh dựa trên các đặc điểm kỹ thuật loại đưa ra trên dòng lệnh.

$ printf '%s\n' 'a b' 'a c' | sort -uk 1,1
a b
$ printf '%s\n' 'a b' 'a c' | sort -k 1,1 | uniq
a b
a c

$ printf '%s\n' 0 -0 +0 00 '' | sort -n | uniq
0
-0
+0
00

$ printf '%s\n' 0 -0 +0 00 '' | sort -nu
0

9

Tôi thích sử dụng sort | uniqvì khi tôi cố gắng sử dụng -utùy chọn (loại bỏ trùng lặp) để loại bỏ các trùng lặp liên quan đến chuỗi trường hợp hỗn hợp, không dễ để hiểu kết quả.

Lưu ý: trước khi bạn có thể chạy các ví dụ bên dưới, bạn cần mô phỏng trình tự đối chiếu C tiêu chuẩn bằng cách thực hiện như sau:

LC_ALL=C
export LC_ALL

Ví dụ, nếu tôi muốn sắp xếp một tệp và loại bỏ trùng lặp, đồng thời, giữ cho các trường hợp khác nhau của chuỗi khác nhau.

$ cat short      #file to sort
Pear
Pear
apple
pear
Apple

$ sort short     #normal sort (in normal C collating sequence)
Apple            #the lower case words are at the end
Pear
Pear
apple
pear

$ sort -f short  #correctly sorts ignoring the C collating order
Apple            #but duplicates are still there
apple
Pear
Pear
pear

$ sort -fu short #By adding the -u option to remove duplicates it is 
apple            #difficult to ascertain the logic that sort uses to remove
Pear             #duplicates(i.e., why did it remove pear instead of Pear?)

Sự nhầm lẫn này được giải quyết bằng cách không sử dụng -utùy chọn để loại bỏ trùng lặp. Sử dụng uniqlà dễ dự đoán hơn. Dưới đây đầu tiên sắp xếp và bỏ qua các trường hợp và sau đó vượt qua nó uniqđể loại bỏ các bản sao.

$ sort -f short | uniq
Apple
apple
Pear
pear

2
-utùy chọn sortđầu ra đầu tiên của một lần chạy bằng nhau (xem trang man). Do đó, sort -fuchọn ra sự xuất hiện đầu tiên của mỗi dòng duy nhất không phân biệt chữ hoa chữ thường. Logic sortsử dụng để loại bỏ trùng lặp là có thể dự đoán.
pallxk

3

Một sự khác biệt khác mà tôi phát hiện ra hôm nay là khi sắp xếp dựa trên một phân số trong đó chỉ sort -uáp dụng cờ duy nhất trên cột mà bạn sắp xếp.

$ cat input.csv
3,World,1
1,Hello,1
2,Hello,1

$ cat input.csv | sort -t',' -k2 -u
1,Hello,1
3,World,1

$ cat input.csv | sort -t',' -k2 | uniq
1,Hello,1
2,Hello,1
3,World,1

Điều này được đề cập trong câu trả lời từ Stéphane Chazelas nhưng tôi thích ví dụ của bạn nên +1
roaima

Cảm ơn bạn đã chỉ ra @roaima, câu trả lời không rõ ràng lắm
Stefanos Chrs
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.