2012-02-21 23 views
119

Tôi muốn loại bỏ các mục trùng lặp từ một tập tin văn bản, ví dụ:Hủy bỏ các mục trùng lặp sử dụng một kịch bản Bash

kavitha= Tue Feb 20 14:00 19 IST 2012 (duplicate entry) 
sree=Tue Jan 20 14:05 19 IST 2012 
divya = Tue Jan 20 14:20 19 IST 2012 
anusha=Tue Jan 20 14:45 19 IST 2012 
kavitha= Tue Feb 20 14:00 19 IST 2012 (duplicate entry) 

Có cách nào có thể loại bỏ các mục trùng lặp sử dụng một kịch bản Bash?

đầu ra mong muốn

kavitha= Tue Feb 20 14:00 19 IST 2012 
sree=Tue Jan 20 14:05 19 IST 2012 
divya = Tue Jan 20 14:20 19 IST 2012 
anusha=Tue Jan 20 14:45 19 IST 2012 
+17

* Yêu cầu làm thế nào để loại bỏ các bản sao. Câu hỏi được đánh dấu là trùng lặp. * – sysfiend

+0

* Đây là câu hỏi về việc xóa các mục trùng lặp. Nó đã được đánh dấu là trùng lặp. * –

Trả lời

264

Bạn có thể sort sau đó uniq:

$ sort -u input.txt 

Hoặc sử dụng awk:

$ awk '!a[$0]++' input.txt 
+38

Thử nghiệm với tệp văn bản dòng 18.500: 'sort ...' mất khoảng 0,57 giây trong khi 'awk ...' mất khoảng 0,08 giây vì 'awk ...' chỉ xóa các từ khóa trùng lặp mà không sắp xếp. – Hugo

+2

@Hugo Tôi có thể làm được điều đó. Thử nghiệm với 2.626,198 dòng 'awk' nhịp đập 'sắp xếp'. Kết quả cho thấy 'awk' lấy 5.675s và 'sort' lấy 5.675s. Điều thú vị là cùng một bản ghi đã mất 15,1 giây để thực hiện truy vấn MySQL DISTINCT. –

+0

@TeganSnyder Bạn đã viết cả hai lệnh đều mất chính xác cùng một lúc để thực thi. Không phải là 'awk' mất ít thời gian hơn? – jarno

7

Nó xóa trùng lặp, dây chuyền liên tục từ một f ile (mô phỏng "uniq").
Dòng đầu tiên trong một tập hợp các dòng trùng lặp được lưu giữ, phần còn lại sẽ bị xóa.

sed '$!N; /^\(.*\)\n\1$/!P; D' 
+0

làm việc cho tôi, Thêm một lần nữa để sử dụng khác, Nếu bạn muốn thay đổi tệp chính nó ở đây là lệnh 'sed -i' $! N; /^\(.*\)\n\1$/!P; D ' ' –

0

Điều này có thể làm việc cho bạn:

cat -n file.txt | 
sort -u -k2,7 | 
sort -n | 
sed 's/.*\t/ /;s/\([0-9]\{4\}\).*/\1/' 

hay này:

awk '{line=substr($0,1,match($0,/[0-9][0-9][0-9][0-9]/)+3);sub(/^/," ",line);if(!dup[line]++)print line}' file.txt 
2

Perl one-liner tương tự như giải pháp awk @ kev của:

perl -ne 'print if ! $a{$_}++' input 

Sự thay đổi này xóa khoảng trắng theo sau trước khi so sánh:

perl -lne 's/\s*$//; print if ! $a{$_}++' input 

biến thể này chỉnh sửa các tập tin tại chỗ:

perl -i -ne 'print if ! $a{$_}++' input 

biến thể này chỉnh sửa các tập tin tại chỗ, và làm cho một bản sao lưu input.bak

perl -i.bak -ne 'print if ! $a{$_}++' input 
Các vấn đề liên quan