http://www.perlmonks.org?node_id=11149572


in reply to Re: bug or curly bracket hell?
in thread bug or curly bracket hell?

I'm still a perl beginner, When I declare my variables it still gives me, "Global symbol "%s" requires explicit package name" Can you give me some tips on fixing that? My coworker the programmer here codes in perl but doesnt seem to use strict for that very same reason.

Replies are listed 'Best First'.
Re^3: bug or curly bracket hell?
by hippo (Archbishop) on Jan 13, 2023 at 16:45 UTC
    "Global symbol "%s" requires explicit package name" Can you give me some tips on fixing that?

    You have chopped off the last part of the error message and that was the bit which explains how you can fix it.

    $ perl -Mstrict -e '%s = ();' Global symbol "%s" requires explicit package name (did you forget to d +eclare "my %s"?) at -e line 1. Execution of -e aborted due to compilation errors. $ perl -Mstrict -e 'my %s = ();' $

    See: my and our.


    🦛

      okay lets say I have this code to access a server/database and I have repeating variables and these are the repeating errors I have on strict. Variable "$VARDB_DATABASE" is not imported AT PROJECT.PL LINE 43. I get this for the other variables as well then Global symbol "$VARDB_DATABASE" requires explicit package name AT PROJECT LINE 43. Keep in mind this works with out strict for me. (paragraph)

      #path to astguiclient configuration file: $PATHconf = '/etc/astguiclient.conf'; open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n"; @conf = <conf>; close(conf); my $i=0; foreach(@conf){ $line = $conf[$i]; $line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi; if ( ($line =~ /^PATHlogs/) && ($CLIlogs < 1) ) {$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;} if ( ($line =~ /^PATHsounds/) && ($CLIsounds < 1) ) {$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;} if ( ($line =~ /^VARserver_ip/) && ($CLIserver_ip < 1) ) {$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;} if ( ($line =~ /^VARDB_server/) && ($CLIDB_server < 1) ) {$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;} if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) ) {$VARDB_database = $line; my $VARDB_database =~ s/.*=//gi;} if ( ($line =~ /^VARDB_user/) && ($CLIDB_user < 1) ) {$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;} if ( ($line =~ /^VARDB_pass/) && ($CLIDB_pass < 1) ) {$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;} if ( ($line =~ /^VARDB_custom_user/) && ($CLIDB_custom_user < 1) ) {$VARDB_custom_user = $line; $VARDB_custom_user =~ s/.*=//gi +;} if ( ($line =~ /^VARDB_custom_pass/) && ($CLIDB_custom_pass < 1) ) {$VARDB_custom_pass = $line; $VARDB_custom_pass =~ s/.*=//gi; +} if ( ($line =~ /^VARDB_port/) && ($CLIDB_port < 1) ) {$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;} $i++; } if (!$VARDB_port) {$VARDB_port='3306';} use strict; use warnings; use Excel::Writer::XLSX; use DBI; use Time::Piece; use Math::Round; my $t = "" . $i; my $dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$ +VARDB_port", "$VARDB_user", "$VARDB_pass") or die "Couldn't connect to database: " . DBI->errstr;
        if ( ($line =~ /^VARDB_database/) && ($CLIDB_database < 1) ) {$VARDB_database = $line; my $VARDB_database =~ s/.*=//gi;}
        With strict enabled you can't do certain things that make no sense, like declaring a variable with "my" after you already used that variable.
Re^3: bug or curly bracket hell?
by GrandFather (Saint) on Jan 13, 2023 at 23:02 UTC

    First off: 'code smells' are coding styles that are fragile or hard to maintain (probably because they are hard to read). use strict helps address some forms of code smell if used sensibly. One thing that can make a huge difference is to ensure variables are used in the smallest sensible scope - strict helps that by telling you where an undeclared variable is first used.

    A very closely related technique is to initialise scalar variables (variables that start with $) where they are declared. Sometimes array and hash variables can be usefully initialised where they are declared too, but often they are used to accumulate entries in following code and don't need an explicit initialisation value at declaration (they are born empty).

    The golden rule: Always use strictures (use strict; use warnings; - see The strictures, according to Seuss).

    Strictures, especially strict, tell you about things that are easy to get wrong and hard to find, like changing the spelling of an identifier. Using lexical variables (variables declared with my) limits their scope to the enclosing block (within the enclosing { } pair) which helps in understanding how variables are used and avoids misusing variables.

    Fixing a bad smell can often end up with a jolly good clean out of the whole fridge to everyone's benefit. Adopting the use of strictures is a good start to cleaning up smelly code.

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
      Adopting the use of strictures is a good start to cleaning up smelly code

      Absolutely seconded!

      I resisted at first but since following the teaching wise monks, my code has been less smelly, giving me an easier and more pleasant coding life.

      I was able to shorten my code by 100 lines taking in the advice. I can use it with perl -c, but I've run into another issue.. I'm getting use of uniniatlized value for each DB varible in the SQL part of the code to connect to the db, for example use of uniniatlized value $VARDB_database in concatenation or string at line 29. Each line the program reads it says, argument "SRC 125,Emma,,boston,,in,48011,8123456787" isnt numeric in array element at line 118. input same line is: SRC 125 "Emma Boston IN 48011 8127429212 emmaboston2011@icloud.com." its a 20000 line excel doc. Tried googling the error codes and ask my coworker but no such luck, my coworker and the one before him have never bothered with strict so all of our perl scripts don't use it. This is what I have now.
      print " use strict; use warnings; use Excel::Writer::XLSX; use DBI; use Time::Piece; use Math::Round; #path to astguiclient configuration file: my $PATHconf = '/etc/astguiclient.conf'; my ( $PATHlogs, $VARserver_ip, $VARDB_server, $VARDB_database, $VARDB_user, $VARDB_pass, $VARDB_custom_user, $VARDB_custom_pass, $VARDB_port); open('conf', "$PATHconf") || die "can't open $PATHconf: $!\n"; my @conf = <conf>; close('conf'); my $i=0; foreach(@conf){ my $line = $conf[$i]; my $t= "".$i; my $dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$ +VARDB_port", "$VARDB_user", "$VARDB_pass") or die "Couldn't connect to database: " . DBI->errstr; my $rowCount = 0; my $filename = "Output012023.xlsx"; my $workbook = Excel::Writer::XLSX->new( $filename ); open(FH, "<", "Debt.csv" ) or die; my $worksheet = $workbook->add_worksheet('List'); my $worksheet2 = $workbook->add_worksheet('List2'); my $format = $workbook->add_format(); my $format1 = $workbook->add_format(); #my $format2 = $workbook->add_format(); $format->set_center_across(); $format1->set_color( 'red' ); #$format2->set_bold(); #print join("\n", map { s|/|::|g; s|\.pm$||; $_ } keys %INC); #proper format must be used for the file or it will give an error $worksheet->set_column( 8, 8, 20 ); $worksheet->set_column( 10, 10, 15 ); $worksheet->set_column( 4, 4, 18 ); #$worksheet->set_column( 5, 5, 15 ); #$worksheet->set_column( 12, 12, 65 ); $worksheet->write(0, 0, "source_id" ); $worksheet->write(0, 1, "first_name" ); $worksheet->write(0, 2, "middle" ); $worksheet->write(0, 3, "last_name" ); $worksheet->write(0, 4, "address1" ); $worksheet->write(0, 5, "city"); $worksheet->write(0, 6, "state"); $worksheet->write(0, 7, "postal_code"); $worksheet->write(0, 8, "phone_number"); $worksheet->write(0, 9, "address3"); $worksheet->write(0, 10,"province"); $worksheet->write(0, 11, "email"); my $rowCount1 = my $rowCount2 = 0; #$worksheet2->set_column( 8, 8, 20 ); #$worksheet2->set_column( 10, 10, 15 ); #$worksheet2->set_column( 4, 4, 20 ); #$worksheet2->set_column( 5, 5, 15 ); #$worksheet2->set_column( 12, 12, 62 ); $worksheet2->write(0, 0, "source_id" ); $worksheet2->write(0, 1, "first_name" ); $worksheet2->write(0, 2, "middle" ); $worksheet2->write(0, 3, "last_name" ); $worksheet2->write(0, 4, "address1" ); $worksheet2->write(0, 5, "city"); $worksheet2->write(0, 6, "state"); $worksheet2->write(0, 7, "postal_code"); $worksheet2->write(0, 8, "phone_number"); $worksheet2->write(0, 9, "address3"); $worksheet2->write(0, 10,"province"); $worksheet2->write(0, 11, "email"); my $test=0; my $oZ=0; #RowCount1 writes for the whole page then 100 lines later it goes +to rowcoutn2 may need changed while (<FH>){ chomp; my @t= split(',',$_); if (length($t[8]) == 10) { # && (length($t[7])==4 || length($ +t[7])==5)) { if (!defined($t[7]) || $t[7] eq ''){ my $stmt ="SELECT postal_code, state FROM asterisk.vic +idial_postal_codes WHERE state='".$t[6]."' limit 1;"; my $sth = $dbhA->prepare($stmt) or die "preparing: ",$ +dbhA->errstr; $sth->execute or die "executing: $stmt ", $dbhA->errst +r; my $sthrows= $sth->rows; my $Count=0; #$z=""; while($sthrows>$Count) { my @ary = $sth->fetchrow_array; $worksheet->write($rowCount1+1, $_, $t[$_]); $worksheet->write($rowCount1+1, $_, $ary[$_]); $Count++; } } else { if (!defined($t[6]) || $t[6] eq '' || length($t[6])>2 +|| length($t[6])<2){ my $stmt = "SELECT state, postal_code FROM asteris +k.vicidial_postal_codes WHERE postal_code='".$t[7]."' Limit 1;"; my $sth = $dbhA->prepare($stmt) or die "preparing: + ",$dbhA->errstr; $sth->execute or die "executing: $stmt ", $dbhA->e +rrstr; my $sthrows=$sth->rows; my $Count=0; while($sthrows>$Count){ my @ary = $sth->fetchrow_array; $worksheet2->write($rowCount2+1, $_, $t[$_]); $worksheet2->write($rowCount2+1, $_, $ary[$_]) +; $Count++; } } else { $worksheet->write($rowCount1+1, $_, $t[$_]); } $rowCount1++; } } else { my $z=""; if (!defined($t[7]) || $t[7] eq '' || length($t[7])>5 || l +ength($t[7])<=3){ my $stmt="SELECT postal_code, state FROM asterisk.vici +dial_postal_codes WHERE state='".$t[6]."' and postal_code not in ('00 +501','00544') limit 1;"; my $sth = $dbhA->prepare($stmt) or die "preparing: ",$ +dbhA->errstr; $sth->execute or die "executing:$stmt ", $dbhA->errstr +; my $sthrows= $sth->rows; my $Count=0; $oZ=$t[7]; while($sthrows>$Count){ my @ary = $sth->fetchrow_array; $z=$ary[0]; $worksheet2->write($rowCount2+1, $_, $t[$_]); $worksheet2->write($rowCount2+1, $_, $ary[$_]); $Count++; } } else { if (!defined($t[6]) || $t[6] eq '' || length($t[6])>2 +|| length($t[6])<2){ my $stmt="SELECT state, postal_code FROM asterisk. +vicidial_postal_codes WHERE postal_code='".$t[7]."' Limit 1;"; my $sth = $dbhA->prepare($stmt) or die "preparing: + ",$dbhA->errstr; $sth->execute or die "executing: $stmt ", $dbhA->e +rrstr; my $sthrows=$sth->rows; my $Count=0; while($sthrows>$Count){ my @ary = $sth->fetchrow_array; $worksheet2->write($rowCount2+1, $_, $t[$_]); $worksheet2->write($rowCount2+1, $_, $ary[$_]) +; $Count++; } } else { $worksheet2->write($rowCount2+1, $_, $t[$_]) } } if (length($t[8]) < 10 || length($t[8]) > 10){ $worksheet2->write($rowCount2+1, 12, 'phone is incorre +ct.', $format1); } if (defined($z) || $z ne ''){ $worksheet2->write($rowCount2+1, 12, $oZ.' Zip code ha +s been updated '.$z.'.', $format1); } elsif (length($t[8]) < 10 || length($t[8]) > 10) { $worksheet2->write($rowCount2+1, 12, ' Zip code update +d, but has bad phone. ', $format1); } $rowCount2++; } } $rowCount++; } my $workbook->close(); #print $rowCount1.'-'.$rowCount2.'-'.$rowCount; close(FH);\n";

        You have a bogus 'print "' at the start of your code. The closing quote for that string is 'open('conf', "' (many lines later). All of the apparent use statements and my declarations, in the intervening code, are just part of the string; they are not Perl statements that will be executed.

        — Ken

          my $PATHconf = '/etc/astguiclient.conf'; # declared and initialized
        
          my ( # declared with "my" but not initialized
          $PATHlogs,
          $VARserver_ip,
          $VARDB_server,
          $VARDB_database,
          $VARDB_user,
          $VARDB_pass,
          $VARDB_custom_user,
          $VARDB_custom_pass,
          $VARDB_port); 
        
        You need to initialize your declared variables by defining their values:
          my $PATHconf       = '/etc/astguiclient.conf';
          my $PATHlogs       = '/path/to/logs';
          my $VARserver_ip   = '1.2.3.4';
          my $VARDB_server   = 'your_db_server';
          my $VARDB_database = 'name_of_database';
          my $VARDB_user     = 'the_db_username';
          my $VARDB_pass     = 'the_db_password';