Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly use Global variables in perl

Tags:

perl

I am a novice to perl. I'm trying to understand it by writing some programs. Scoping in perl is giving me a hard time.

I wrote the following:

use 5.16.3;
use strict;
use Getopt::Long;

Getopt::Long::Configure(qw(bundling no_getopt_compat));
&ArgParser;
our ($sqluser,$sqlpass);

$sqluser="root";
$sqlpass="mypassword";

sub ArgParser {
    print "Username is ".$sqluser." Password is ".$sqlpass."\n";
    my $crt='';
    my $delete='';
    GetOptions ('create|c=s' => \$crt,
        'delete|d=s' => \$delete
    );
    if ($crt) {
        &DatabaseExec("create",$crt);   
    } elsif ($delete) {
        &DatabaseExec("delete",$delete);    
    } else {
    print "No options chosen\n";
    }
}

sub DatabaseExec {
    use DBI;
    my $dbname=$_[1];
    print "Username is ".$sqluser." Password is ".$sqlpass."\n";
    my $dbh = DBI->connect("dbi:mysql:", $sqluser,$sqlpass);
    my $comand=$_[0];
    if ($_[0] eq "create") {
        my $db_com="create database ".$dbname;
        print 1 == $dbh->do($db_com) ? "Database created\n":"An error occured while creating database. Maybe it exists?\n";
        #print "Executing: ".$db_com."\n";
    } elsif ($_[0] eq "delete") {
        my $db_com="DROP DATABASE ".$dbname;
        #print "Executing: ".$db_com."\n";
        print 1 == $dbh->do($db_com) ? "Database deleted\n":"An error occured while creating database. Maybe it exists?\n";
    }
}

It was my understanding that our would declare these as global variables for the use of the main code, and subroutines. However this gives the following output:

#~/perlscripts/dbtest.pl -c hellos
Use of uninitialized value $sqluser in concatenation (.) or string at /root/perlscripts/dbtest.pl line 20.
Use of uninitialized value $sqlpass in concatenation (.) or string at /root/perlscripts/dbtest.pl line 20.
Username is  Password is
Use of uninitialized value $sqluser in concatenation (.) or string at /root/perlscripts/dbtest.pl line 44.
Use of uninitialized value $sqlpass in concatenation (.) or string at /root/perlscripts/dbtest.pl line 44.
Username is  Password is
DBI connect('','',...) failed: Access denied for user 'root'@'localhost' (using password: NO) at /root/perlscripts/dbtest.pl line 45.
Can't call method "do" on an undefined value at /root/perlscripts/dbtest.pl line 50.

I would not like to pass these as arguments to the sub, and would rather use them as global variables. Could someone help me determine my misunderstanding of scoping?

like image 379
Joel G Mathew Avatar asked Apr 16 '13 11:04

Joel G Mathew


People also ask

How do you set a global variable in Perl?

Global variables can be used inside any function or any block created within the program. It is visible in the whole program. Global variables can directly use and are accessible from every part of the program. Example 1: The variable $name is declared at the beginning of the code.

What does $@ mean in Perl?

In these cases the value of $@ is the compile error, or the argument to die.

What is $$ in Perl?

$$ The process number of the perl running this script. (Mnemonic: same as shells.) $? The status returned by the last pipe close, backtick (\`\`) command or system operator.

What is $_ in Perl script?

The most commonly used special variable is $_, which contains the default input and pattern-searching string. For example, in the following lines − #!/usr/bin/perl foreach ('hickory','dickory','doc') { print $_; print "\n"; }


1 Answers

Your variables are not declared when your subroutine is called:

&ArgParser;                 # subroutine call
our ($sqluser,$sqlpass);    # declaration

$sqluser="root";            # assignment
$sqlpass="mypassword";

In order to use these global variables inside the subroutine, put the subroutine after the variable declaration.

However, using global variables is a bad thing, and you should avoid it whenever possible. You can do this instead, for example:

my $sqluser = "root";
my $sqlpass = "mypass";

ArgParser($sqluser, $sqlpass);    # you should not use & in subroutine calls

And then inside the subroutine:

sub ArgParser {
    my ($sqluser, $sqlpass) = @_;
    ...

This way, your variables are nicely encapsulated and safe from being manipulated accidentally.

Regarding the ampersand & in your subroutine call, this is documented in perldoc perlsub:

To call subroutines:

NAME(LIST);   # & is optional with parentheses.
NAME LIST;    # Parentheses optional if predeclared/imported.
&NAME(LIST);  # Circumvent prototypes.
&NAME;        # Makes current @_ visible to called subroutine.
like image 148
TLP Avatar answered Sep 25 '22 17:09

TLP