views:

318

answers:

4

Closing this question. Will drink red bull. Sleep. Code and come back with brand spanking new question with unit test cases.

UPDATE: The new file is here

Also the config file is here

I refactored the code again:

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

This code always dies here die("$ETLSplitter::name is not specified in the config file");.

Another clue is that if I change split (':', $cols); to split (/:/, $cols); I get this 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.
+3  A: 

Are you sure that it's stuck? You never store any data in @columns, so your code will always return an empty list.

Other notes:

  • Your die call should include $! (OS error). There are other reasons that the open could fail besides a non-existent file, and $! will tell you what the real problem was.
  • You should probably do a chomp $conline to get rid of the newline.
  • You can do while (my $conline = <CFILE>) instead of copying the value from $_.
  • Two-argument open (particularly with an implicit < mode) is poor form. Using the three-argument form (ideally with a lexical filehandle) is preferred: open(my $fh, '<', $filename) or die...
Michael Carman
+6  A: 

FINAL POST FOR THIS QUESTION: Based on your latest updates, I believe the following code illustrates how there is no problem with using /:/ as the first argument to split. It also points out that it is easier to read code when one uses arguments to functions rather than relying on global variables:

#!/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'
        ];

There is a lot of cruft in that code. Here is my interpretation of what you are trying to do:

UPDATE: Given your recent remark about regex special characters in patterns, if you are going to use them in the pattern to split, make sure to quote them. There is also a chance that $ETLSpliter::name might contain other special characters. I modified the code to deal with that possibility.

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

ANOTHER UPDATE:

So, the pattern indeed is /=>/ based on your comment below. Then:

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'
        ];

No errors ... No warnings Therefore, there is something else that is going on which you insist on not showing us.

Other Remarks:

  1. Use lexical filehandles and let perl tell you what errors it may encounter rather than presuming.

  2. Declare variables in the smallest applicable scope.

  3. No need to assign $_ to $conline in the body of the loop when you can do that in the while statement.

  4. In the original code, you were not putting anything in @columns or doing anything useful with $colData.

  5. Tone down the rhetoric. Computers work on the principle of GIGO.

  6. Looking at the code at the link you posted, it looks like you are not aware that you can do:

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

Further, it looks like you are using a package where hash would have done the job:

$ETLSpliter{filepath}

Finally, you do realize Spliter is incorrect. ITYM: Splitter.

Sinan Ünür
even then as soon as I use the / character in the loop it breaks? Why is that? I am using perl on cygwin and the file is in [dos] mode in vim? will that make a difference?
kthakore
Because you decided to use `/` as the pattern delimiter. No, platform and editor do not make any difference.
Sinan Ünür
Umm ... still failing due to split(/pattern/, $foo) usage. I have to use split('pattern', $foo). Don't get why this is happening. I am going to implement the changes you said and let me re post the file.
kthakore
What is in the pattern? If the pattern contains what you posted, I don't see the problem. If the pattern contains something other than what you posted, well, why did you that? And why don't you go ahead and post what really is in the pattern?
Sinan Ünür
oops srry. split(/=>/, $conline). $conline looks like this cpr_operator_detail=>3:11:18:28:124:220:228:324
kthakore
ok ... Can you stop accusing me of not showing enough information. I have posted the whole file, explained my platform. .... What else do you need? I am at a loss of what the hell is going on too...
kthakore
Your code says `split /=>/`. In a comment to your question, you mention putting a `/` somewhere in there. There is no error with `split /=>/`. You are getting errors. Therefore, it is reasonable to assume that what you are running and what you posted are not one and the same.
Sinan Ünür
Dude I understand that your code is super great awesome. I am still trying to find out why the hell is this not working in my code.
kthakore
I just noticed that you seem to be trying to write complete Perl programs on the command line. Maybe that has something to do with it. The downvote is completely unjustified. You can compare what you are doing with what I am doing and figure out where you are putting the G in GI so the computer is giving you GO. In the mean time, this question has become too convoluted.
Sinan Ünür
Ok I agree. Closing this post. Will drink red bull. Sleep. Code and come back with brand spanking new question with unit test cases.
kthakore
If anything, please avoid Red Bull for a while.
Sinan Ünür
thx for bearing with me btw
kthakore
ok ... |@__@| no red bull
kthakore
how do I close a question
kthakore
Don't worry about it. If enough people vote to close it, it will be closed. Thank you for accepting my answer. I hope it will be useful.
Sinan Ünür
you could simply delete the question. There ought to be a link to do that somewhere.
innaM
+1  A: 

What's in $ETLSpliter::name - any / chars there should be escaped.

Many other issues in the snippet have already been addressed so I won't go there.

laalto
Why should slashed be escaped in that string?
innaM
Manni due to winblows
kthakore
I beg your pardon?
innaM
A: 

FINALLY FIGURED IT OUT!!!!! Wow Sleep is awesome power.

Anyway. The problem was in $ETLSplitter::configFile in my die message.

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

Which has winblows path separators '/'. So because I was outputting in double quotation, perl interperted the '/' in the path as patterns. From here

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

to

...  /=>/,

Which messed with the entire program flow in the subroutine. This was solved by doing this.

die ('Error opening '.$ETLSpliter::configFile.': '.$!);
kthakore
I don't see any difference between the first and the last die statement. I guess when you say winblows you are referring to MS-Windows? But since when is the slash a path separator on Windows? This doesn't make any kind of sense. Sorry.
innaM
ya it didn't to me either until I printed out $ETLSpliter::configFile. it has //10.0.1.1/ it in due to local intranet ip. Thats what was messing it up.
kthakore