In dòng độc đáo


15

Có một số giải pháp tốt hơn để in các dòng độc đáo ngoài sự kết hợp sortuniq?


1
Bạn có ý nghĩa gì bởi "tốt hơn"?
gabe.

@gabe Không yêu cầu toàn bộ tệp được lưu trữ trong bộ nhớ chẳng hạn.
Let_Me_Be

Một số phiên bản của sort(ví dụ: GNU coreutils) sử dụng các tệp tạm thời và hợp nhất bên ngoài nếu đầu vào quá lớn để phù hợp với RAM. Và hầu hết các phiên bản khác đều có -mtùy chọn để điều này có thể được thực hiện một cách rõ ràng bằng cách phân đoạn đầu vào (ví dụ: với split), sắp xếp từng đoạn, sau đó hợp nhất các đoạn
jhnc

Câu trả lời:


25

Để in mỗi dòng giống nhau chỉ một, theo bất kỳ thứ tự nào:

sort -u

Để chỉ in các dòng duy nhất, theo bất kỳ thứ tự nào:

sort | uniq -u

Để chỉ in mỗi dòng giống nhau một lần, theo thứ tự xuất hiện đầu tiên của chúng: (đối với mỗi dòng, hãy in dòng nếu nó chưa được nhìn thấy, sau đó, trong mọi trường hợp, hãy tăng bộ đếm nhìn thấy)

awk '!seen[$0] {print}
     {++seen[$0]}'

Để chỉ in các dòng duy nhất, theo thứ tự xuất hiện đầu tiên của chúng: (ghi lại từng dòng seenvà cả linesnếu đó là lần xuất hiện đầu tiên; ở cuối đầu vào, hãy in các dòng theo thứ tự xuất hiện nhưng chỉ những dòng được nhìn thấy Một lần)

awk '!seen[$0]++ {lines[i++]=$0}
     END {for (i in lines) if (seen[lines[i]]==1) print lines[i]}'

8
làm thế nào về awk '!seen[$0]++ {print}'?
asoundmove

10
Hoặc thậm chí ngắn hơn awk '!seen[$0]++', vì {print}được ngụ ý bởi một lệnh trống.
quazgar

3

Một số phiên bản (hầu hết?) sort-ucờ uniqtrực tiếp. Có thể một số hạn chế độ dài dòng tùy thuộc vào việc triển khai, nhưng bạn đã có những hạn chế với đơn giản sort|uniq.


1
Ơ sort -uquay trở lại V7 ít nhất
geekizard

Hum ... Tôi nghĩ rằng tôi nhớ Solaris hoặc AIX không có điều đó. Mặc dù tôi sai, cả hai đều có nó.
Mat

Solaris và AIX có -unhưng cũng có giới hạn độ dài dòng 512 ký tự. (Trên thực tế, tôi nghĩ rằng ở đâu đó xung quanh Solaris 9 Sun upped nó để 5120. GNU vẫn thắng, mặc dù.)
geekosaur

@geekizard: bạn có chắc không? Công việc được thực hiện để loại bỏ giới hạn 512 byte về độ dài dòng theo cách đã được ghi lại trong 'Lý thuyết và thực hành trong việc xây dựng một quy trình sắp xếp công việc' của JP Linderman, Kỹ thuật hệ thống Bell. Tạp chí, 63, 1827-1843 (1984).
Jonathan Leffler

0

Perl có làm việc cho bạn không? Nó có thể giữ các dòng theo thứ tự ban đầu, ngay cả khi các bản sao không liền kề. Bạn cũng có thể mã nó bằng Python, hoặc awk.

while (<>) {
    print if $lines{$_}++ == 0;
}

Mà có thể rút ngắn lại chỉ

perl -ne 'print unless $lines{$_}++;'

Cho tập tin đầu vào:

abc
def
abc
ghi
abc
def
abc
ghi
jkl

Nó mang lại đầu ra:

abc
def
ghi
jkl

$ Line được định nghĩa ở đâu?
Gregg Leventhal

Không phải vậy. Vì không có use strict;hoặc use warnings;(thực ra, nó strictcó liên quan nhất ở đây), không có khiếu nại về việc sử dụng %linestrước khi nó được xác định. Nếu chạy với độ nghiêm ngặt, cần phải có một dòng my %lines;trước vòng lặp. Lưu ý rằng, băm là %lines; một yếu tố của hàm băm được tham chiếu bằng cách sử dụng $lines{$_}ký hiệu.
Jonathan Leffler

Tôi nghĩ rằng các sortgiải pháp có thể tốt hơn cho lượng dữ liệu lớn (OP quan tâm đến việc "lưu trữ toàn bộ tệp trong bộ nhớ"). sortsẽ thực hiện sắp xếp ngoài lõi nếu dữ liệu lớn hơn bộ nhớ khả dụng.
Kusalananda

0

Đối với phần cuối của câu trả lời được đề cập trong: In các dòng duy nhất của @Gilles như một câu trả lời cho câu hỏi này, tôi đã cố gắng loại bỏ sự cần thiết phải sử dụng hai hàm băm.

Giải pháp này dành cho: Để chỉ in các dòng duy nhất, theo thứ tự xuất hiện đầu tiên của chúng:

awk '{counter[$0]++} END {for (line in counter) if (counter[line]==1) print line}'

Ở đây, "bộ đếm" lưu trữ số lượng của mỗi dòng tương tự như dòng được xử lý trước đó.
Cuối cùng, chúng tôi chỉ in những dòng đó, có giá trị truy cập là 1.

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.