2009-03-13 15 views
6

Để sử dụng lệnh uniq, trước tiên bạn phải sắp xếp tệp của mình.Làm thế nào để giữ định dạng của tệp nếu bạn sử dụng lệnh uniq (trong trình bao)?

Nhưng trong tệp tôi có, thứ tự của thông tin là quan trọng, do đó làm cách nào để giữ nguyên định dạng gốc của tệp nhưng vẫn loại bỏ nội dung trùng lặp?

+0

Bạn muốn giữ lại chỉ xuất hiện đầu tiên của mô hình? Hay chỉ là người cuối cùng? Bạn phải cụ thể hơn một chút ... – wzzrd

+0

Đây là một tập tin như thế này. pattern1 pattern2 pattern3 pattern4 pattern1 pattern2 vv ... pattern1 khác với pattern2, và vân vân. Ví dụ: pattern1 là một tiêu đề và pattern2 là số điện thoại. Nếu tôi sắp xếp tệp, số điện thoại sẽ không nằm dưới tiêu đề phải, v.v. – Dennis

+0

Tôi quên phần nhận xét này không giữ nguyên định dạng. Vì vậy, bài đăng trên có thể hơi khó hiểu. – Dennis

Trả lời

10

Một phiên bản awk:

awk '!_[$0]++' infile 
+0

O (n) giải pháp trong 8 byte. +1 – ashawley

+0

haha, dễ thương! làm thế nào nó hoạt động? (+1) –

+0

ah, bây giờ tôi thấy :) –

0

Bạn có thể sử dụng một số O khủng khiếp (n^2) điều, như thế này (Pseudo-code):

file2 = EMPTY_FILE 
for each line in file1: 
    if not line in file2: 
    file2.append(line) 

Đây là tiềm năng khá chậm, đặc biệt là nếu thực hiện ở cấp Bash. Nhưng nếu các tệp của bạn là hợp lý ngắn, có thể nó sẽ hoạt động tốt và sẽ nhanh chóng triển khai (not line in file2 sau đó chỉ là grep -v, v.v.).

Nếu không, bạn có thể mã hóa một chương trình chuyên dụng, sử dụng một số cấu trúc dữ liệu nâng cao hơn trong bộ nhớ để tăng tốc.

+0

Cảm ơn bạn đã thư giãn. Các tập tin tôi có ngay bây giờ chỉ là một tập tin mẫu vì vậy nó khá ngắn. Nhưng các tập tin tôi sẽ sử dụng nó sẽ lớn. Tôi sẽ xem những gì người khác đề nghị, và tôi có thể sẽ thử đề xuất của bạn cho bây giờ. – Dennis

1

Bạn có thể chạy -d uniq trên phiên bản sắp xếp các tập tin để tìm các dòng trùng lặp, sau đó chạy một số kịch bản nói rằng:

if this_line is in duplicate_lines { 
    if not i_have_seen[this_line] { 
     output this_line 
     i_have_seen[this_line] = true 
    } 
} else { 
    output this_line 
} 
+0

Lợi ích của việc này là trái ngược với các giải pháp đơn giản hơn một chút, btw, là bạn không giữ bản đồ của mọi dòng trong tệp, chỉ có các dòng trùng lặp. – chaos

+0

oh chờ đã. đã không nghĩ về -d. ngớ ngẩn litb. cũng t comm có thể được cắt ra sau đó ủng hộ nó :) –

+0

phiên bản cuối cùng sau khi đưa vào -d thay vì sử dụng comm: sort file.txt | uniq -d | awk 'FNR == NR {dups [$ 0]; } FNR! = NR {if ($ 0 trong dups) {if (! ($ 0 trong dòng)) {print $ 0; dòng [$ 0]; }} else in $ 0; } '- file.txt –

4

awk Điều này sẽ giúp sự xuất hiện đầu tiên. Cùng thuật toán như câu trả lời khác sử dụng:

awk '!($0 in lines) { print $0; lines[$0]; }' 

Đây là một loại chỉ cần để lưu trữ các dòng trùng lặp (như trái ngược với tất cả các dòng) sử dụng awk:

sort file | uniq -d | awk ' 
    FNR == NR { dups[$0] } 
    FNR != NR && (!($0 in dups) || !lines[$0]++) 
' - file 
0
for line in $(sort file1 | uniq); do 
    grep -n -m1 line file >>out 
done; 

sort -n out 

đầu tiên thực hiện sắp xếp,

cho mỗi grep giá trị uniqe cho kết quả đầu tiên (-m1)

và bảo toàn số dòng

sắp xếp đầu ra bằng số (-n) theo số dòng.

sau đó bạn có thể loại bỏ các dòng # 's với sed hay awk

4

Ngoài ra còn có những "line-số, kích đúp loại" phương pháp.

nl -n ln | sort -u -k 2| sort -k 1n | cut -f 2- 
+0

+1 cho giải pháp hoạt động với các tệp rất lớn. Nhưng không phải đó là "sắp xếp -k 1n" (kiểu số)? –

+0

vâng, bạn nói đúng. – ashawley

1

Chỉ sử dụng uniq và grep:

Tạo d.sh:

#!/bin/sh 
sort $1 | uniq > $1_uniq 
for line in $(cat $1); do 
cat $1_uniq | grep -m1 $line >> $1_out 
cat $1_uniq | grep -v $line > $1_uniq2 
mv $1_uniq2 $1_uniq 
done; 
rm $1_uniq 

Ví dụ:

./d.sh infile 
Các vấn đề liên quan