Làm thế nào là uniq không đủ độc đáo mà còn có uniq --unique?


35

Dưới đây là các lệnh trên một tệp ngẫu nhiên từ pastebin :

wget -qO - http://pastebin.com/0cSPs9LR | wc -l
350
wget -qO - http://pastebin.com/0cSPs9LR | sort -u | wc -l
287
wget -qO - http://pastebin.com/0cSPs9LR | sort | uniq | wc -l
287
wget -qO - http://pastebin.com/0cSPs9LR | sort | uniq -u | wc -l
258

Các trang người đàn ông không rõ ràng về những gì -ucờ đang làm. Có lời khuyên nào không?


4
Hãy thử sắp xếp | uniq -d | wc -l và bạn có thể nhận ra sự khác biệt. :)
stoeff

Câu trả lời:


42

Phiên bản ngắn:

  • uniq, không có -u, làm cho mỗi dòng đầu ra là duy nhất.
  • uniq -uchỉ in mỗi dòng duy nhất từ đầu vào .

Phiên bản dài hơn một chút:

uniqlà để xử lý các tệp có các dòng trùng lặp và chỉ khi các dòng đó xuất hiện liên tiếp trong đầu vào. Vì vậy, với mục đích của nó, một dòng duy nhất là một dòng không bị trùng lặp ngay lập tức.

( uniqcó bộ nhớ ngắn hạn rất hạn chế; nó sẽ không bao giờ nhớ liệu một dòng xuất hiện sớm hơn trong đầu vào hay không, trừ khi đó là dòng ngay trước đó - đây là lý do tại sao uniqrất thường được ghép nối với sort.)

Khi nó gặp phải một dòng trùng lặp uniq, không có đối số -u, sẽ in một bản sao của dòng đó. (Nó làm cho mỗi dòng của đầu ra là duy nhất ).

Với -ulập luận, nó in zero bản sao của dòng đó - chạy các bản sao chỉ được bỏ qua từ đầu ra.


1
Tôi thực sự muốn có một tùy chọn để không yêu cầu sắp xếp. Nhưng nó sẽ yêu cầu giữ toàn bộ tệp trong bộ nhớ (hoặc thực hiện nhiều thao tác ghi sổ với giá trị băm và bù trừ nếu nguồn là tệp bình thường)
Random832

3
@ Random832: và nó sẽ yêu cầu quyết định nên giữ bản sao nào (đầu tiên, cuối cùng, một cái gì khác, có thể định cấu hình) và quyết định đó sẽ ảnh hưởng đến thuật toán trên toàn cầu. Rắc rối.
Steve Jessop

1
@ Random832: nếu chỉ là về số lượng ký tự để nhập, bạn có thể sử dụng sort -uthay vì sort | uniq.
oliver

@oliver Thỉnh thoảng tôi muốn có một khả năng giữ phiên bản đầu tiên của bất kỳ dòng nào mà không sắp xếp lại chúng và viết các kịch bản để làm như vậy.
Random832

1
@hvd: nếu phiên bản của uniqbạn không chuẩn hóa và đối chiếu, có. Nhưng ngay cả khi đó chỉ là một sự cân nhắc cục bộ - bạn biết nơi nào trong đầu ra được sắp xếp, dòng sẽ xuất hiện và chỉ cần chọn một trong số các dòng liền kề để giữ. Nếu đầu vào không được sắp xếp thì quyết định sẽ ảnh hưởng đến toàn bộ hoạt động của uniqifying, ví dụ: nếu bạn sẽ giữ bản sao cuối cùng thì bạn không thể xuất bất cứ điều gì cho đến khi bạn đọc dòng cuối cùng của đầu vào ...
Steve Jessop

53

uniqvới -ubỏ qua bất kỳ dòng nào có trùng lặp. Như vậy:

$ printf "%s\n" 1 1 2 3 | uniq
1
2
3
$ printf "%s\n" 1 1 2 3 | uniq -u
2
3

Thông thường, uniqin các dòng nhiều nhất một lần (giả sử đầu vào được sắp xếp). Tùy chọn này thực sự in các dòng thực sự độc đáo (không xuất hiện lại).


11
Đó là, uniqcó thể được gọi distinct, vì nó in tất cả các dòng riêng biệt, trong khi uniq -uin tất cả các dòng duy nhất.
Steve Jessop

Nó không thực sự độc đáo với GNU uniqở một số địa phương.
cuonglm

Tôi đã phải đọc câu trả lời được chấp nhận nhiều lần, nhưng nó không bị chìm. Ví dụ và đoạn văn của bạn sau khi nó rất rõ ràng (và quay lại và đọc lại câu trả lời được chấp nhận, tôi cũng hiểu điều đó) :)
Madivad

18

thông số kỹ thuật POSIX uniq mô tả rõ ràng:

-u
    Suppress the writing of lines that are repeated in the input.

-utùy chọn uniqkhông in các dòng lặp lại.

Hầu hết các uniqtriển khai đã sử dụng so sánh byte, trong khi GNU uniqsử dụng thứ tự đối chiếu để lọc các dòng trùng lặp. Vì vậy, nó có thể tạo ra kết quả sai ở một số địa phương, ví dụ tại en_US.UTF-8miền địa phương:

$ printf '%b\n' '\U2460' '\U2461' | uniq
①

và không -ucho bạn dòng nào:

$ printf '%b\n' '\U2460' '\U2461' | uniq -u
<blank>

Vì vậy, bạn nên đặt miền địa phương Cđể lấy byte so sánh:

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C uniq
①
②

3
Lưu ý rằng những gì sai ở đây không nhiều uniq(mặc dù rõ ràng mục đích của POSIX là nó nên thực hiện so sánh byte thay vì so sánh strcoll () như trong sort -u) như những địa phương có lỗi sắp xếp giống như. Ít nhất GNU uniqphù hợp với sort -u.
Stéphane Chazelas

@ StéphaneChazelas - nơi nào trong thông số kỹ thuật được làm rõ ràng?
mikeerv

Về uniqyêu cầu phải làm memcmp / strcmp trái ngược với strcoll, điều đó không rõ ràng đối với tôi nhưng đó là với Geoff . Về các địa điểm GNU có ① sắp xếp giống như, đó rõ ràng là một lỗi vì không có lý do tại sao chúng nên sắp xếp giống nhau. Điều đó được POSIX cho phép nhưng sẽ có một số thay đổi .
Stéphane Chazelas

8

bình thường:

echo "a b a b c c c" | tr ' ' '\n'
a
b
a
b
c
c
c

uniq: không có hai dòng lặp lại tiếp theo

echo "a b a b c c c" | tr ' ' '\n' | uniq
a
b
a
b
c

đã sắp xếp

echo "a b a b c c c" | tr ' ' '\n' | sort
a
a
b
b
c
c
c

sort -u: không có hai dòng lặp lại

echo "a b a b c c c" | tr ' ' '\n' | sort -u
a
b
c

sort / uniq: tất cả khác biệt

echo "a b a b c c c" | tr ' ' '\n' | sort | uniq
a
b
c

đếm sự xuất hiện khác biệt

echo "a b a b c c c" | tr ' ' '\n' | sort | uniq -c
2 a
2 b
3 c

chỉ những dòng không được lặp lại (không được sắp xếp trước)

echo "a b a b c c c" | tr ' ' '\n' | uniq -u
a
b
a
b

chỉ những dòng không được lặp lại (sau khi sắp xếp)

echo "a b a b c c c Z" | tr ' ' '\n' | sort | uniq -u
Z

uniq -d: chỉ in các dòng trùng lặp, một dòng cho mỗi nhóm

echo "a b a b c c c" | tr ' ' '\n' | uniq -d
c

.. đã tính

echo "a b a b c c c" | tr ' ' '\n' | uniq -dc
3 c

ví dụ rõ ràng tốt đẹp :)
Madivad
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.