2010-11-04 35 views
8

Tengo un archivo csv de 40 MB con 50,000 registros. Es una lista gigante de productos. Cada fila tiene cerca de 20 campos. [# Artículo, UPC, la descripción, etc.]Secuencia de comandos para encontrar duplicados en un archivo csv

¿Cómo puedo,

a) encontrar e imprimir las filas duplicadas. [Este archivo es un archivo adjunto grande, así que tengo múltiples encabezados incluidos en el archivo que necesito eliminar, así que quería saber las filas exactas que están duplicadas primero.]

b) Buscar e imprimir filas duplicadas en función de una columna. [Vea si un UPC está asignado a múltiples productos]

Necesito ejecutar el comando o script en el servidor y tengo instalados Perl y Python. Incluso el script bash o el comando funcionarán para mí también.

No necesito conservar el orden de las filas. etc

he intentado,

tipo largefile.csv | uniq -d

para obtener los duplicados, pero no recibo la respuesta esperada.

Idealmente me gustaría bash script o comando, pero si alguien tiene alguna otra sugerencia, sería genial también.

Gracias


Ver: Remove duplicate rows from a large file in Python sobre desbordamiento de pila

+5

¿por qué no 'uniq-d' te da la respuesta esperada? – dogbane

+0

Debe mostrar algunos datos de muestra (desinfectar si es necesario), incluidos los que considera que son duplicados y no duplicados. Específicamente, si el primer campo (elemento #) es diferente, pero el segundo campo (UPC) es el mismo o si todo el registro es el mismo, etc. También debe ser más específico sobre lo que "No obtengo la respuesta esperada". "significa. 'uniq' solo mira la línea completa a menos que le indique que omita una parte de la línea (pero no usa comas como separadores de campo). Además, los archivos CSV pueden ser difíciles de manejar a menos que uses herramientas creadas para tal fin (por ejemplo, una lib de Python). –

Respuesta

2

lo que pueda utilizar la cáscara de SQLite para importar su archivo CSV y crear índices para ejecutar comandos SQL más rápido.

8

encontrar e imprimir las filas duplicadas en Perl:

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

Buscar y filas de impresión con columnas duplicadas en Perl - Digamos que la quinta columna de donde los campos están separados por comas:

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

Vale la pena señalar que este último funciona si y solo si los datos CSV nunca contienen un separador entre comillas '1,2,' 3,3 ', 4'. – RedGrittyBrick

+0

@mob: parece que para cualquier grupo de filas duplicadas, la última fila no se imprime con este ejemplo. –

0

Para la segunda parte: lea el archivo con Text :: CSV en un código hash en su (s) clave (s) única (s), verifique si existe un valor para el hash antes de agregarlo.Algo como esto:

datos (no tiene que ser resuelto), en este ejemplo necesitamos las dos primeras columnas a ser único:

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 

código:

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"; 
    } 
} 

que imprime algo como esto:

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

Pruebe lo siguiente:

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

uniq es un comando muy básico y sólo informa singularidad/duplicados que son uno junto al otro.

+0

tiene dos tipos de ordenación. – tmow

+0

Lo he editado. – tmow

+0

He intentado también la versión de Perl aquí abajo y es más rápido que esto, al menos en el shell de Ubuntu en Windows10. Pero ambos están funcionando bien – user2548436

1

Aquí mi (muy simple) script para hacerlo con Ruby & Rake Gem.

En primer lugar crear un Rakefile y escribir este código:

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 

Luego de usarlo en la primera columna

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

Y para usarlo en la segunda (por ejemplo)

$ rake csv:double["2017.04.07-Export.csv",1] 
File contains duplicates 
Cuestiones relacionadas