Làm thế nào để chỉ nhận được kết quả duy nhất mà không phải sắp xếp dữ liệu?


40
$ cat data.txt 
aaaaaa
aaaaaa
cccccc
aaaaaa
aaaaaa
bbbbbb
$ cat data.txt | uniq
aaaaaa
cccccc
aaaaaa
bbbbbb
$ cat data.txt | sort | uniq
aaaaaa
bbbbbb
cccccc
$

Kết quả mà tôi cần là hiển thị tất cả các dòng từ tệp gốc loại bỏ tất cả các bản sao (không chỉ các dòng liên tiếp), trong khi duy trì thứ tự ban đầu của các câu lệnh trong tệp .

Ở đây, trong ví dụ này, kết quả mà tôi thực sự đang tìm kiếm là

aaaaaa
cccccc
bbbbbb

Làm thế nào tôi có thể thực hiện uniqhoạt động tổng quát này nói chung?

Câu trả lời:


54
perl -ne 'print unless $seen{$_}++' data.txt

Hoặc, nếu bạn phải sử dụng vô íchcat :

cat data.txt | perl -ne 'print unless $seen{$_}++'

Đây là awkbản dịch dành cho các hệ thống thiếu Perl:

awk '!seen[$0]++' data.txt
cat data.txt | awk '!seen[$0]++'

3
Một kịch bản awk ngắn hơn một chút là{ if (!seen[$0]++) print }
camh

1
@fred, trừ khi tệp của bạn thực sự rất lớn, một trong hai phiên bản sẽ mất nhiều thời gian hơn để nhập.
cjm

8
Phiên bản awk có thể được thực hiện thậm chí ngắn hơn bằng cách bỏ ra if, print, dấu ngoặc đơn, và niềng răng:awk '!seen[$0]++'
Gordon Davisson

2
@Legate, đó là tên của một mảng trong đó chúng tôi ghi lại mọi dòng chúng tôi đã thấy. Bạn có thể thay đổi nó thành '!LarryWall[$0]++'cho tất cả sự quan tâm, nhưng "thấy" giúp mọi người hiểu rõ hơn về chương trình.
cjm

1
@Sadi, điều đó thực sự nên được hỏi như một câu hỏi, không phải là một bình luận. Nhưng một số dòng trong tệp đó kết thúc trong một khoảng trắng, và một số thì không. Các lệnh này xem xét toàn bộ dòng có ý nghĩa, bao gồm cả khoảng trắng ở cuối.
cjm

13

john có một công cụ gọi là unique:

usr@srv % cat data.txt | unique out
usr@srv % cat out
aaaaaa
cccccc
bbbbbb

Để đạt được điều tương tự mà không cần các công cụ bổ sung trong một dòng lệnh thì phức tạp hơn một chút:

usr@srv % cat data.txt | nl | sort -k 2 | uniq -f 1 | sort -n | sed 's/\s*[0-9]\+\s\+//'
aaaaaa
cccccc
bbbbbb

nlin số dòng ở phía trước các dòng, vì vậy nếu chúng ta sort/ uniqđằng sau chúng, chúng ta có thể khôi phục lại thứ tự ban đầu của các dòng. sedchỉ xóa các số dòng sau đó;)


Có sự kết hợp nào của các lệnh linux phổ biến có thể làm tương tự không?
Lazer

7
Bạn đã bỏ lỡ điều gì trong "mà không phải sắp xếp dữ liệu"?
Totor

@Totor - xem trả lời của menkus cho một nhận xét tương tự. @binfalse - giải pháp thứ hai của bạn không hoạt động (có thể nó hoạt động với mẫu tầm thường này nhưng nó không hoạt động với một số đầu vào thực tế). Vui lòng sửa nó, ví dụ: cái này sẽ luôn hoạt động:nl -ba -nrz data.txt | sort -k2 -u | sort | cut -f2
don_crissti

6

Tôi thích sử dụng này:

cat -n data.txt | sort --key=2.1 -b -u | sort -n | cut -c8-

cat -n thêm số dòng,

sort --key=2.1 -b -u sắp xếp trên trường thứ hai (sau số dòng được thêm vào), bỏ qua khoảng trống hàng đầu, giữ các dòng duy nhất

sort -n sắp xếp theo thứ tự số nghiêm ngặt

cut -c8- giữ tất cả các ký tự từ cột 8 đến EOL (nghĩa là bỏ qua các số dòng chúng tôi đưa vào)


5
> Làm thế nào để chỉ nhận được kết quả duy nhất mà không phải sắp xếp dữ liệu? > mà không phải sắp xếp dữ liệu
Jan Wikholm

7
'mà không phải sắp xếp dữ liệu' chỉ xuất hiện trong tiêu đề. Nhu cầu thực tế là: "hiển thị tất cả các dòng từ tệp gốc loại bỏ tất cả các bản sao (không chỉ các dòng liên tiếp), trong khi duy trì thứ tự ban đầu của các câu lệnh trong tệp."
menkus

1
@menkus khóa là "trong khi duy trì thứ tự ban đầu của câu lệnh trong tệp". Câu trả lời này không đạt được điều đó.
Andrew Ferrier

2

Perl có một mô-đun mà bạn có thể sử dụng bao gồm một hàm được gọi uniq. Vì vậy, nếu bạn đã tải dữ liệu của mình trong một mảng trong Perl, bạn chỉ cần gọi hàm như thế này để làm cho nó là duy nhất, nhưng vẫn duy trì thứ tự ban đầu.

use List::MoreUtils qw(uniq)    
@output = uniq(@output);

Bạn có thể đọc thêm về mô-đun này tại đây: List :: MoreUtils


Điều này có thể xử lý các tệp lớn, ví dụ 500 GB?
Cậu bé
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.