2010-11-04 39 views
8

Tôi có tệp csv 40 MB với 50.000 bản ghi. Đó là một danh sách sản phẩm khổng lồ. Mỗi hàng có gần 20 trường. [Mã số, UPC, Mô tả, v.v.]Tập lệnh để tìm các bản sao trong tệp csv

Làm cách nào để có thể,

a) Tìm và in hàng trùng lặp. [Tệp này là một tệp được nối thêm lớn, vì vậy tôi có nhiều tiêu đề được bao gồm trong tệp mà tôi cần xóa, vì vậy tôi muốn biết các hàng chính xác trùng lặp trước tiên.]

b) Tìm và in các hàng trùng lặp dựa trên một cột. [Xem liệu UPC có được gán cho nhiều sản phẩm hay không]

Tôi cần chạy lệnh hoặc tập lệnh trên máy chủ và tôi đã cài đặt Perl và Python. Ngay cả bash script hoặc lệnh sẽ làm việc cho tôi quá.

Tôi không cần phải giữ nguyên thứ tự của các hàng. vv

tôi đã cố gắng,

loại largefile.csv | uniq -d

để nhận các bản sao, Nhưng tôi không nhận được câu trả lời mong đợi.

Lý tưởng nhất là tôi muốn tập lệnh bash hoặc lệnh, nhưng nếu có bất kỳ đề xuất nào khác, điều đó cũng tuyệt vời.

Cảm ơn


Xem: Remove duplicate rows from a large file in Python qua trên Stack Overflow

+5

tại sao 'uniq -d' không cho bạn câu trả lời mong đợi? – dogbane

+0

Bạn nên hiển thị một số dữ liệu mẫu (đã được vệ sinh nếu cần), bao gồm cả những gì bạn cho là trùng lặp và không trùng lặp. Cụ thể, nếu trường đầu tiên (mụC#) khác nhau, nhưng trường thứ hai (UPC) là giống nhau hoặc nếu toàn bộ bản ghi là giống nhau, v.v. Bạn cũng nên cụ thể hơn về những gì "Tôi không nhận được câu trả lời mong đợi " có nghĩa. 'uniq' chỉ xem xét toàn bộ dòng trừ khi bạn yêu cầu nó bỏ qua một phần của dòng (nhưng nó không sử dụng dấu phẩy làm dấu tách trường). Ngoài ra, các tệp CSV có thể khó giải quyết trừ khi bạn đang sử dụng các công cụ được thực hiện cho mục đích (ví dụ: một thư viện Python). –

Trả lời

2

Bạn có thể có thể sử dụng vỏ SQLite để import file csv của bạn và tạo chỉ mục để thực hiện các lệnh SQL nhanh hơn.

8

Tìm và in hàng trùng lặp trong Perl:

perl -ne 'print if $SEEN{$_}++' < input-file 

Tìm và các hàng in với các cột trùng lặp trong Perl - giả sử cột thứ 5 của nơi lĩnh vực được phân cách bằng dấu phẩy:

perl -F/,/ -ane 'print if $SEEN{$F[4]}++' < input-file 
+0

Điều đáng chú ý là tác phẩm thứ hai chỉ khi và dữ liệu CSV không bao giờ chứa dấu tách trích dẫn '1,2," 3,3 ", 4'. – RedGrittyBrick

+0

@mob: Dường như đối với bất kỳ nhóm hàng trùng lặp nào, hàng cuối cùng không được in với ví dụ này. –

0

Đối với phần thứ hai: hãy đọc tệp có Văn bản :: CSV thành một khóa băm trên (các) khóa duy nhất của bạn, kiểm tra xem giá trị có tồn tại cho băm trước khi thêm nó hay không.Một cái gì đó như thế này:

dữ liệu (không cần phải được sắp xếp), trong ví dụ này chúng ta cần hai cột đầu tiên là duy nhất:

1142,X426,Name1,Thing1 
1142,X426,Name2,Thing2 
1142,X426,Name3,Thing3 
1142,X426,Name4,Thing4 
1144,X427,Name5,Thing5 
1144,X427,Name6,Thing6 
1144,X427,Name7,Thing7 
1144,X427,Name8,Thing8 

mã:

use strict; 
use warnings; 
use Text::CSV; 

my %data; 
my %dupes; 
my @rows; 
my $csv = Text::CSV->new() 
         or die "Cannot use CSV: ".Text::CSV->error_diag(); 

open my $fh, "<", "data.csv" or die "data.csv: $!"; 
while (my $row = $csv->getline($fh)) { 
    # insert row into row list 
    push @rows, $row; 
    # join the unique keys with the 
    # perl 'multidimensional array emulation' 
    # subscript character 
    my $key = join($;, @{$row}[0,1]); 
    # if it was just one field, just use 
    # my $key = $row->[$keyfieldindex]; 
    # if you were checking for full line duplicates (header lines): 
    # my $key = join($;, @$row); 
    # if %data has an entry for the record, add it to dupes 
    if (exists $data{$key}) { # duplicate 
     # if it isn't already duplicated 
     # add this row and the original 
     if (not exists $dupes{$key}) { 
      push @{$dupes{$key}}, $data{$key}; 
     } 
     # add the duplicate row 
     push @{$dupes{$key}}, $row; 
    } else { 
     $data{ $key } = $row; 
    } 
} 

$csv->eof or $csv->error_diag(); 
close $fh; 
# print out duplicates: 
warn "Duplicate Values:\n"; 
warn "-----------------\n"; 
foreach my $key (keys %dupes) { 
    my @keys = split($;, $key); 
    warn "Key: @keys\n"; 
    foreach my $dupe (@{$dupes{$key}}) { 
     warn "\tData: @$dupe\n"; 
    } 
} 

nào in ra một cái gì đó như thế này:

Duplicate Values: 
----------------- 
Key: 1142 X426 
    Data: 1142 X426 Name1 Thing1 
    Data: 1142 X426 Name2 Thing2 
    Data: 1142 X426 Name3 Thing3 
    Data: 1142 X426 Name4 Thing4 
Key: 1144 X427 
    Data: 1144 X427 Name5 Thing5 
    Data: 1144 X427 Name6 Thing6 
    Data: 1144 X427 Name7 Thing7 
    Data: 1144 X427 Name8 Thing8 
8

Hãy thử cách sau:

# Sort before using the uniq command 
sort largefile.csv | sort | uniq -d 

uniq là lệnh rất cơ bản và chỉ báo cáo tính duy nhất/trùng lặp là cạnh nhau.

+0

bạn có hai lần sắp xếp. – tmow

+0

Tôi đã chỉnh sửa nó. – tmow

+0

Tôi cũng đã thử phiên bản perl ở đây và nhanh hơn thant này, ít nhất là trong ubuntu shell trên windows10. Nhưng cả hai đều đang làm việc tuyệt vời – user2548436

1

Đây là tập lệnh (rất đơn giản) của tôi để làm điều đó với Ruby & Rake Gem.

Đầu tiên tạo một RakeFile và viết mã này:

namespace :csv do 
    desc "find duplicates from CSV file on given column" 
    task :double, [:file, :column] do |t, args| 
    args.with_defaults(column: 0) 
    values = [] 
    index = args.column.to_i 
    # parse given file row by row 
    File.open(args.file, "r").each_slice(1) do |line| 
     # get value of the given column 
     values << line.first.split(';')[index] 
    end 
    # compare length with & without uniq method 
    puts values.uniq.length == values.length ? "File does not contain duplicates" : "File contains duplicates" 
    end 
end 

Sau đó, để sử dụng nó trên cột đầu tiên

$ rake csv:double["2017.04.07-Export.csv"] 
File does not contain duplicates 

Và để sử dụng nó trên giây (ví dụ)

$ rake csv:double["2017.04.07-Export.csv",1] 
File contains duplicates 
Các vấn đề liên quan