Pregunta

Cerrando esta pregunta. Beberá Red Bull. Dormir. Codifique y vuelva con una nueva y sorprendente pregunta con casos de prueba de unidad.

ACTUALIZACIÓN: El nuevo archivo está aquí

También el archivo de configuración es aquí

Refactoré el código nuevamente:

sub getColumns {
    open my $input, '<', $ETLSplitter::configFile
        or die "Error opening '$ETLSpliter::configFile': $!";

    my $cols;
    while( my $conline = <$input> ) {
        chomp $conline;
        my @values = split (/=>/, $conline);
        if ($ETLSplitter::name =~ $values[0] ) {
            $cols = $values[1];
            last;
        }
    }

    if($cols) {
        @ETLSplitter::columns = split (':', $cols);
    }
    else {
        die("$ETLSplitter::name is not specified in the config file");
    }
}

Este código siempre muere aquí die("$ETLSplitter::name is not specified in the config file");.

Otra pista es que si cambio split (':', $cols); a split (/:/, $cols); me sale este error.

 perl -wle "
 use modules::ETLSplitter;
 \$test = ETLSplitter->new('cpr_operator_metric_actual_d2', 'frame/');
 \$test->prepareCSV();"
 syntax error at modules/ETLSplitter.pm line 154, near "}continue"
 Compilation failed in require at -e line 2.
 BEGIN failed--compilation aborted at -e line 2.
¿Fue útil?

Solución

PUBLICACIÓN FINAL PARA ESTA PREGUNTA: Según sus últimas actualizaciones, creo que el siguiente código ilustra cómo no hay problema al usar /:/ como primer argumento para split. También señala que es más fácil leer el código cuando uno usa argumentos para funciones en lugar de depender de variables globales:

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

for my $varname ( qw( adntopr.cpr.smtref.actv cpr_operator_detail )) {
    print $varname, "\n";
    print Dumper get_columns(\*DATA, $varname);
}

sub get_columns {
    my ($input_fh, $varname) = @_;

    while ( my $line = <$input_fh> ) {
        chomp $line;
        my @values = split /=>/, $line;
        next unless $varname eq $values[0];
        return [ split /:/, $values[1] ];
    }
    return;
}

__DATA__
adntopr.cpr.smtref.actv=>3:8:18:29:34:38:46:51:53:149
adntopr.smtsale2=>3:8:16:22:27:37:39:47:52:57:62:82:102:120:138:234:239:244:249:250:259:262:277:282:287:289:304:319:327:331:335:339:340:341:342:353:364:375:386:397:408
cpr_operator_detail=>3:11:18:28:124:220:228:324
cpr_operator_org_unit_map=>7:12
cpr_operator_metric_actual=>8:15:25:33:38:40:51

C:\Temp> tjm
adntopr.cpr.smtref.actv
$VAR1 = [
          '3',
          '8',
          '18',
          '29',
          '34',
          '38',
          '46',
          '51',
          '53',
          '149'
        ];
cpr_operator_detail
$VAR1 = [
          '3',
          '11',
          '18',
          '28',
          '124',
          '220',
          '228',
          '324'
        ];

Hay mucho cruft en ese código. Aquí está mi interpretación de lo que está tratando de hacer:

ACTUALIZACIÓN: Teniendo en cuenta su comentario reciente sobre los caracteres especiales de expresiones regulares en los patrones, si los va a usar en el patrón para dividir, asegúrese de citarlos. También existe la posibilidad de que $ETLSpliter::name pueda contener otros caracteres especiales. Modifiqué el código para hacer frente a esa posibilidad.

sub getColumns {
    open my $input, '<', $ETLSpliter::configFile
          or die "Error opening '$ETLSpliter::configFile': $!");
      my @columns;
      while( my $conline = <$input> ) {
          my @values = split /=>/, $conline;
          print "not at: ".$conline;
          push @columns, $values[1] if $values[0] =~ /\Q$ETLSpliter::name/;
      }
      return @columns;
  }

OTRA ACTUALIZACIÓN:

Entonces, el patrón es /=>/ basado en su comentario a continuación. Entonces:

my $conline = q{cpr_operator_detail=>3:11:18:28:124:220:228:324};
my @values = split /=>/, $conline;

use Data::Dumper;
print Dumper \@values;
__END__

C:\Temp> tml
$VAR1 = [
          'cpr_operator_detail',
          '3:11:18:28:124:220:228:324'
        ];

Sin errores ... Sin advertencias Por lo tanto, está sucediendo algo más que insiste en no mostrarnos.

Otras observaciones:

  1. Use manejadores de archivos léxicos y deje que Perl le diga qué errores puede encontrar en lugar de suponer.

  2. Declarar variables en el alcance más pequeño aplicable.

  3. No es necesario asignar $_ a $conline en el cuerpo del bucle cuando puede hacerlo en la declaración while.

  4. En el código original, no estaba poniendo nada en @columns o haciendo nada útil con $colData.

  5. Reduce la retórica. Las computadoras funcionan según el principio de GIGO.

  6. Mirando el código en el enlace que publicaste , parece que no eres consciente de que puedes hacer:

    use File::Spec::Functions qw( catfile );
    ...
    catfile($ETLSpliter::filepath_results, $ETLSpliter::actual_name);
    

Además, parece que está utilizando un paquete donde el hash habría hecho el trabajo:

$ETLSpliter{filepath}

Finalmente, te das cuenta de que Spliter es incorrecto. ITYM: Splitter.

Otros consejos

¿Estás seguro de que está atascado? Nunca almacena ningún dato en @columns, por lo que su código siempre devolverá una lista vacía.

Otras notas:

  • Su die llamada debe incluir $! (error del sistema operativo). Hay otras razones por las que open podría fallar además de un archivo inexistente, y chomp $conline le dirá cuál era el verdadero problema.
  • Probablemente deberías hacer un while (my $conline = <CFILE>) para deshacerte de la nueva línea.
  • Puede hacer $_ en lugar de copiar el valor de <.
  • Dos argumentos open(my $fh, '<', $filename) or die... (particularmente con un modo <=> implícito) es una forma pobre. Se prefiere usar la forma de tres argumentos (idealmente con un identificador de archivo léxico): <=>

¿Qué hay en $ETLSpliter::name? Cualquier / carácter que haya debe escaparse.

Ya se han solucionado muchos otros problemas en el fragmento, por lo que no iré allí.

¡FINALMENTE LO RESULTÉ! Wow Sleep es un poder increíble.

De todos modos. El problema estaba en $ ETLSplitter :: configFile en mi mensaje de matriz.

die ('Error opening '.$ETLSpliter::configFile.': '.$!);

Que tiene separadores de ruta winblows '/'. Entonces, como estaba generando comillas dobles, Perl interceptó el '/' en la ruta como patrones. Desde aquí

die "Error opening some/path/to/ ...

a

...  /=>/, 

Que se metió con todo el flujo del programa en la subrutina. Esto se resolvió haciendo esto.

<*>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top