WBWARD has asked for the wisdom of the Perl Monks concerning the following question:

I need guidance and enlightenment! My goal is to parse my database file into separate section that I can modify separately. One problem I have is that my sku's should be 7 characters long, but somehow got leading zeros dropped. I receive this error when attempting to run my script. "Undefined subroutine &main::OPEN called at C:\Perl\sku_corr2.pl line 8." I am running 5.12.3 on Windows 7 64.
#!/usr/bin/perl -w $| = 1; $MYFILE = "apr_products_tab.csv"; $outfile = "./sku.txt"; OPEN (MYFILE, $MYFILE) || die "Cannot open $MYFILE, aborting program." +; OPEN (PRINTER, "> $outfile") || die "Cannot open sku.txt, aborting pro +gram. $!\n"; while (<MYFILE>) { chomp; my ($_ID,$CAT_ID,$TITLE,$SHORT_DESC,$FULL_DESC,$META_TITLE,$META_K +EYWORDS,$META_DESCRIPTION,$THUMB_IMAGE,$DETAIL_IMAGE,$LARGE_IMAGE,$LI +ST_PRICE,$PRICE,$SALE_PRICE,$FLAT_RATE_SHIPPING,$IN_STOCK,$NUM_SOLD,$ +WEIGHT,$BOX_LENGTH,$BOX_WIDTH,$BOX_HEIGHT,$MAX_PER_BOX,$CHARGE_SHIPPI +NG,$REALTIME_OVERRIDE,$CHARGE_TAX,$IS_NEW,$IS_FEATURED,$SHIP_SEPERATL +Y,$VIEWABLE,$ORDERABLE,$REWARDS_EARNABLE,$REWARDS_REDEEMABLE,$REQUIRE +_ADDTOCART,$AVAIL_TO,$MANUFACTURER,$VENDOR,$SKU) = SPLIT (/\t/, $_, 37); PRINT PRINTER $SKU . "\n"; } CLOSE MYFILE; CLOSE PRINTER;
Thanks for looking. Wade
  • Comment on Error Undefined subroutine &main::OPEN called at C:\Perl\sku_corr2.pl line 8.
  • Download Code

Replies are listed 'Best First'.
Re: Error Undefined subroutine &main::OPEN called at C:\Perl\sku_corr2.pl line 8.
by Marshall (Canon) on May 09, 2011 at 22:40 UTC
    open() and close() are lower case.

    update: change SPLIT to split also.

    I would also add "use strict;" at the top of the script. This will force you to use "my" variables, but will catch a lot of compile time errors.

      Thank you. Your help has narrowed things down to one error message: "Use of uninitialized value $SKU in rr2.pl line 17, <myfile> line 287." The script does print the $sku information to the file too.
      #!/usr/bin/perl -w use strict; $| = 1; my $myfile = "apr_products_tab.csv"; my $newfile = "./sku.txt"; open (myfile, "$myfile") || die "Cannot open $myfile, aborting program +."; open (newfile, "> $newfile") || die "Cannot open sku.txt, aborting pro +gram. $!\n"; while (<myfile>) { chomp; my ($_ID,$CAT_ID,$TITLE,$SHORT_DESC,$FULL_DESC,$META_TITLE,$META_K +EYWORDS,$META_DESCRIPTION,$THUMB_IMAGE,$DETAIL_IMAGE,$LARGE_IMAGE,$LI +ST_PRICE,$PRICE,$SALE_PRICE,$FLAT_RATE_SHIPPING,$IN_STOCK,$NUM_SOLD,$ +WEIGHT,$BOX_LENGTH,$BOX_WIDTH,$BOX_HEIGHT,$MAX_PER_BOX,$CHARGE_SHIPPI +NG,$REALTIME_OVERRIDE,$CHARGE_TAX,$IS_NEW,$IS_FEATURED,$SHIP_SEPERATL +Y,$VIEWABLE,$ORDERABLE,$REWARDS_EARNABLE,$REWARDS_REDEEMABLE,$REQUIRE +_ADDTOCART,$AVAIL_TO,$MANUFACTURER,$VENDOR,$SKU) = split (/\t/, $_, 37); print newfile $SKU . "\n"; } close myfile; close newfile;
        "Use of uninitialized value $SKU in rr2.pl line 17, <myfile> line 287."....means that 286 lines input were processed ok, but something happened on line 287 of the input that caused $SKU to be undefined. I suspect that line 287 is the last line of the file and the problem lies there. I usually skip lines containing only whitespace like this:  next if /^\s*$/; #skip blank lines I don't know for sure what is wrong with line 287 - if you are still having trouble, post that line and we'll noodle on it.

        I would change split (/\t/, $_, 37); to split (/\t/, $_);
        As a reference see Perl Doc on split(). Split is a surprisingly complicated critter! One reason to use a limit param is when you have many, many fields on a line and you just want the first n of them. In your case, you want 37 variables, so the limit should actually be 38!! - one more than the number of variables that you want so that all the kruft gets assigned to an unseen 38th variable in this case. Right now, if there was a 38th, 39th field, they would all get crammed into your $SKU variable (the 37th variable).

        As it turns out, with the syntax that you are using, if you omit the limit, Perl will count up all of the my($x,$y,$z...) variables, see that you have 37 of them, then auto-magically supply a limit of 38 to split! So the best answer is to leave this number off and let Perl do the counting!

        So what happens if there isn't enough data to match up with all of these 37 variables in the my($x,$y,$z...)list, e.g. the data line is too short? You will get null strings, not undef for the variables for which there is no data. I demo this as example 1 below. If you add $h after $g, $h will get a null string from the split and there will be a total of 8 variables assigned.

        Another reason to use a limit is that this overrides the default of discarding any trailing empty fields on the input line. I demo this in example 2,3 below. Here I used arrays so Perl can't count like it can with the OP's code and -1 is used as a limit to mean "huge limit".

        #/usr/bin/perl -w use strict; #### SPLIT DEMO ##### ######## example 1 # spliting to list of variables my $y = 'a:b::'; print "***test string is \'$y\'\n"; my @tok = my ($a,$b,$c,$d,$e,$f,$g) = split(/:/, $y); print "number of created fields, with a-g variables: ".@tok."\n"; print "g=\'$g\'\n"; my $cnt=1; foreach (@tok) { print $cnt++," \'$_\'\n"; } my $x = '::a :b::c:::'; print "***test string is \'$x\'\n"; ####### example 2 splitting to an array #this will split into 6 things, because trailing null fields #are omitted with this form of split my @list = split(/:/,$x); # two arg from of split print 'split(/:/,$x)' ." total tokens are: ". @list. "\n"; ####### example 3 splitting to an array #this will split into 10 fields @list = split (/:/,$x, -1); # 3 arg form of split, -1 "huge limit" print 'split (/:/,$x, -1)'." total tokens are: ". @list . "\n"; print "-1 limit includes the trailing null fields...\n"; $cnt=1; foreach (@list) { print $cnt++," \'$_\'\n"; } __END__ Print out: ***test string is 'a:b::' number of created fields, with a-g variables: 7 g='' 1 'a' 2 'b' 3 '' 4 '' 5 '' 6 '' 7 '' ***test string is '::a :b::c:::' split(/:/,$x) total tokens are: 6 split (/:/,$x, -1) total tokens are: 9 -1 limit includes the trailing null fields... 1 '' 2 '' 3 'a ' 4 'b' 5 '' 6 'c' 7 '' 8 '' 9 ''
        If any of your input lines doesn't have 36 tabs in it, the split will leave $SKU undefined. To avoid the error message, add a line between before the print something like if (!defined $SKU) {$SKU = "<<<undef>>>"}
        When you don't understand a warning or error, use diagnostics
        $ perl -Mwarnings -le " my ( $l, $r ) = split /\s/, 'a b',2; print qq[ +$l$r\n]; " ab $ perl -Mwarnings -le " my ( $l, $r ) = split /\s/, 'a',2; print qq[$l +$r\n]; " Use of uninitialized value $r in concatenation (.) or string at -e lin +e 1. a $ perl -Mdiagnostics -Mwarnings -le " my ( $l, $r ) = split /\s/, 'a', +2; print qq[$l$r\n]; " Use of uninitialized value $r in concatenation (.) or string at -e lin +e 1 (#1) (W uninitialized) An undefined value was used as if it were alread +y defined. It was interpreted as a "" or a 0, but maybe it was a mi +stake. To suppress this warning assign a defined value to your variables. ...*snip*... a
        So maybe you assign a value to $SKU or temporarily disable that warning with
        no warnings 'uninitialized';
Re: Error Undefined subroutine &main::OPEN called at C:\Perl\sku_corr2.pl line 8.
by toolic (Bishop) on May 09, 2011 at 22:42 UTC
Re: Error Undefined subroutine &main::OPEN called at C:\Perl\sku_corr2.pl line 8.
by FunkyMonk (Bishop) on May 09, 2011 at 22:46 UTC
    open is spelt open, not OPEN and the same goes for close, split and print. Perl is case sensitive.

    As to why $SKU isn't printing what you expect, I can't say. You didn't show us a (small) sample of your input.

Re: Error Undefined subroutine &main::OPEN called at C:\Perl\sku_corr2.pl line 8.
by John M. Dlugosz (Monsignor) on May 10, 2011 at 09:32 UTC
    Like I said in the CB, do you realize that Perl is case-sensitive?