2012-06-17 27 views
6

Soy relativamente nuevo en Perl y me he topado con este proyecto que estoy teniendo un momento difícil. El objeto del proyecto es comparar dos archivos csv, uno de los cuales contendría: $ nombre, $ modelo, $ versión y el otro que contendría: $ nombre2, $ disco, $ almacenamiento al final el El archivo RESULTADO contendrá las líneas coincidentes y reunirá la información como sigue: $ nombre, $ modelo, $ versión, $ disco, $ almacenamiento.omitiendo una línea en una matriz, Perl

He logrado hacer esto, pero mi problema es que cuando se rompe uno de los elementos que faltan al programa. Cuando encuentra una línea en el archivo que falta un elemento, se detiene en esa línea. ¿Como puedo solucionar este problema? ¿Alguna sugerencia o una forma de cómo puedo hacer que omita esa línea y continúe?

Aquí está mi código:

open(TESTING, '>testing.csv'); # Names will be printed to this during testing. only .net  ending names should appear 
open(MISSING, '>Missing.csv'); # Lines with missing name feilds will appear here. 

#open (FILE,'C:\Users\hp-laptop\Desktop\file.txt'); 
#my (@array) =<FILE>; 
my @hostname; #stores names 

#close FILE; 
#***** TESTING TO SEE IF ANY OF THE LISTED ITEMS BEGIN WITH A COMMA AND DO NOT HAVE A NAME. 
#***** THESE OBJECTS ARE PLACED INTO THE MISSING ARRAY AND THEN PRINTED OUT IN A SEPERATE 
#***** FILE. 
#open (FILE,'C:\Users\hp-laptop\Desktop\file.txt'); 
#test 
if (open(FILE, "file.txt")) { 

} 
else { 
    die " Cannot open file 1!\n:$!"; 

} 

$count = 0; 
$x  = 0; 
while (<FILE>) { 

    ($name, $model, $version) = split(","); #parsing 

    #print $name; 
    chomp($name, $model, $version); 

    if (($name =~ /^\s*$/) 
     && ($model =~ /^\s*$/) 
     && ($version =~ /^\s*$/)) #if all of the fields are blank (just a blank space) 
    { 

    #do nothing at all 
    } 
    elsif ($name =~ /^\s*$/) { #if name is a blank 
    $name =~ s/^\s*/missing/g; 
    print MISSING "$name,$model,$version\n"; 

    #$hostname[$count]=$name; 
    #$count++; 
    } 
    elsif ($model =~ /^\s*$/) { #if model is blank 
    $model =~ s/^\s*/missing/g; 
    print MISSING"$name,$model,$version\n"; 
    } 
    elsif ($version =~ /^\s*$/) { #if version is blank 
    $version =~ s/^\s*/missing/g; 
    print MISSING "$name,$model,$version\n"; 
    } 

    # Searches for .net to appear in field "$name" if match, it places it into hostname array. 
    if ($name =~ /.net/) { 

    $hostname[$count] = $name; 
    $count++; 
    } 

#searches for a comma in the name feild, puts that into an array and prints the line into the missing file. 
#probably won't have to use this, as I've found a better method to test all of the feilds ($name,$model,$version) 
#and put those into the missing file. Hopefully it works. 
#foreach $line (@array) 
#{ 
#if($line =~ /^\,+/) 
#{ 
#$line =~s/^\,*/missing,/g; 
#$missing[$x]=$line; 
#$x++; 
#} 
#} 

} 
close FILE; 

for my $hostname (@hostname) { 
    print TESTING $hostname . "\n"; 
} 

#for my $missing(@missing) 
#{ 
# print MISSING $missing; 
#} 
if (open(FILE2, "file2.txt")) { #Run this if the open succeeds 

    #open outfile and print starting header 
    open(RESULT, '>resultfile.csv'); 
    print RESULT ("name,Model,version,Disk, storage\n"); 
} 
else { 
    die " Cannot open file 2!\n:$!"; 
} 
$count = 0; 
while ($hostname[$count] ne "") { 
    while (<FILE>) { 
    ($name, $model, $version) = split(","); #parsing 

    #print $name,"\n"; 

    if ($name eq $hostname[$count]) # I think this is the problem area. 
    { 
     print $name, "\n", $hostname[$count], "\n"; 

     #print RESULT"$name,$model,$version,"; 
     #open (FILE2,'C:\Users\hp-laptop\Desktop\file2.txt'); 
     #test 
     if (open(FILE2, "file2.txt")) { 

     } 
     else { 
     die " Cannot open file 2!\n:$!"; 

     } 

     while (<FILE2>) { 
     chomp; 
     ($name2, $Dcount, $vname) = split(","); #parsing 

     if ($name eq $name2) { 
      chomp($version); 
      print RESULT"$name,$model,$version,$Dcount,$vname\n"; 

     } 

     } 

    } 

    $count++; 
    } 

    #open (FILE,'C:\Users\hp-laptop\Desktop\file.txt'); 
    #test 
    if (open(FILE, "file.txt")) { 

    } 
    else { 
    die " Cannot open file 1!\n:$!"; 

    } 

} 

close FILE; 
close RESULT; 
close FILE2; 
+2

En la próxima vez, utilice estrictas en su código, lo protege de errores molestos. –

+0

Por favor, 'use strict;', 'use warnings;', sandee su código correctamente, use la versión de argumento de open con manejadores de archivos léxicos y aprenda a usar las funciones de matriz ('push, map, grep'). – dgw

+1

Sean cuales sean los materiales que utilice para enseñar a usted mismo Perl, le aconsejaría soltarlos: su código se basa en plantillas que van desde simplemente muy anticuadas (identificadores de archivos con nombre global, forma de 2 arg de abierto) hasta incorrectas. No tome esto personalmente, obviamente no es su culpa, pero estaría MUY BIEN atendido al aprender de libros, tutoriales y ejemplos de códigos mucho mejores y más modernos de lo que está usando claramente. – DVK

Respuesta

2

Creo que quieres next, que le permite terminar la iteración actual de inmediato e iniciar el siguiente:

while (<FILE>) { 
    ($name, $model, $version) = split(","); 
    next unless($name && $model && $version); 
    ...; 
    } 

La condición que se utiliza depende de lo valores que aceptará. En mis ejemplos, supongo que todos los valores deben ser verdaderos. Si necesitan no ser la cadena vacía, tal vez usted comprueba la longitud del lugar:

while (<FILE>) { 
    ($name, $model, $version) = split(","); 
    next unless(length($name) && length($model) && length($version)); 
    ...; 
    } 

Si sabe cómo validar cada campo, es posible que tenga subrutinas para aquellos:

while (<FILE>) { 
    ($name, $model, $version) = split(","); 
    next unless(length($name) && is_valid_model($model) && length($version)); 
    ...; 
    } 

sub is_valid_model { ... } 

Ahora solo necesita decidir cómo integrar eso en lo que ya está haciendo.

+0

Muchas gracias por su aporte. Intentaré volver a trabajar mi código con esto y ¡publicar lo que sucede! – user1462038

2

Debe comenzar agregando use strict y use warnings a la parte superior de su programa, y ​​declarando todas las variables con my en el punto de su primer uso. Eso revelará muchos errores simples que de otra manera serían difíciles de detectar.

También debe utilizar los tres parámetros para open de filehandles y léxicas, y el lenguaje Perl para el control de excepciones a la apertura de los archivos es añadir or die a una llamada open. if declaraciones con un bloque vacío para el espacio de desperdicio del camino de éxito y se vuelven ilegibles. Un open llamada debe tener este aspecto

open my $fh, '>', 'myfile' or die "Unable to open file: $!"; 

Por último, es mucho más seguro utilizar un módulo de Perl cuando se está manejando archivos CSV, ya que hay una gran cantidad de riesgos en el uso de un simple split /,/. El módulo Text::CSV ha hecho todo el trabajo por usted y está disponible en CPAN.

Su problema es que, habiendo leído hasta el final del primer archivo, no lo rebobina ni lo vuelve a abrir antes de volver a leer desde el mismo identificador en el segundo ciclo anidado. Eso significa que no se leerán más datos de ese archivo y el programa se comportará como si estuviera vacío.

Es una mala estrategia leer cientos de veces el mismo archivo para emparejar registros en correspondencia. Si el archivo es de un tamaño razonable, debe construir una estructura de datos en la memoria para contener la información. Un hash Perl es ideal, ya que le permite buscar los datos correspondientes a un nombre dado al instante.

He escrito una revisión de tu código que demuestra estos puntos. Sería incómodo para mí probar el código ya que no tengo datos de muestra, pero si continúa teniendo problemas, infórmenos.

use strict; 
use warnings; 

use Text::CSV; 

my $csv = Text::CSV->new; 

my %data; 

# Read the name, model and version from the first file. Write any records 
# that don't have the full three fields to the "MISSING" file 
# 
open my $f1, '<', 'file.txt' or die qq(Cannot open file 1: $!); 

open my $missing, '>', 'Missing.csv' 
    or die qq(Unable to open "MISSING" file for output: $!); 
    # Lines with missing name fields will appear here. 

while (my $line = csv->getline($f1)) { 

    my $name = $line->[0]; 

    if (grep $_, @$line < 3) { 
    $csv->print($missing, $line); 
    } 
    else { 
    $data{$name} = $line if $name =~ /\.net$/i; 
    } 
} 

close $missing; 

# Put a list of .net names found into the testing file 
# 
open my $testing, '>', 'testing.csv' 
    or die qq(Unable to open "TESTING" file for output: $!); 
    # Names will be printed to this during testing. Only ".net" ending names should appear 

print $testing "$_\n" for sort keys %data; 

close $testing; 

# Read the name, disk and storage from the second file and check that the line 
# contains all three fields. Remove the name field from the start and append 
# to the data record with the matching name if it exists. 
# 
open my $f2, '<', 'file2.txt' or die qq(Cannot open file 2: $!); 

while (my $line = $csv->getline($f2)) { 

    next unless grep $_, @$line >= 3; 

    my $name = shift @$line; 
    next unless $name =~ /\.net$/i; 

    my $record = $data{$name}; 
    push @$record, @$line if $record; 
} 

# Print the completed hash. Send each record to the result output if it 
# has the required five fields 
# 
open my $result, '>', 'resultfile.csv' or die qq(Cannot open results file: $!); 

$csv->print($result, qw(name Model version Disk storage)); 

for my $name (sort keys %data) { 

    my $line = $data{$name}; 

    if (grep $_, @$line >= 5) { 
    $csv->print($result, $data{$name}); 
    } 
} 
+0

¡Muchas gracias por esto! al revisar este código, entiendo mejor cómo debo hacerlo. El único problema es que no puedo usar los módulos de CPAN. – user1462038

+0

Si no está "permitido", eso sugiere que se trata de tareas y no simplemente un problema con el que "se haya topado". La revelación completa es solo cortés. – mlp

+0

Lo siento, no. Esto no es tarea. Simplemente no puedo modificar los programas en la computadora que uso. Gracias por su vista de todos modos. – user1462038

Cuestiones relacionadas