I'm trying to load a set of variables as defined by a local configuration file. Not too sure what I'm missing so I'll just post it as a whole.
blub.pl
Code:
#!/usr/bin/perl
use strict;
use warnings;
my $config_file="blub.config";
Config_Loader();
sub Config_Loader {
open(CONFIG,"$config_file") or die("config file not found $config_file");
my @config=<CONFIG>;
close CONFIG;
foreach (@config) {
if ($_ !~ /#/){
if (/\$userdb/){
my @a = split(/=/,$_);
my $userdb = $a[1];
print $userdb;
}
if (/\$extention/){
}
print $userdb;
my @charlist = `ls profiles/`;
foreach(@charlist){print $_;}
}
}
}
Here's the config file in which I'm reading from:
Code:
# blub.config
# profiles/
$userdb=profiles/
# ignore following line
$another=blah/
When executed, I receive this error:
Code:
Global symbol "$userdb" requires explicit package name at ./blub.pl line 29.
Execution of ./blub.pl aborted due to compilation errors.
It works if I take out line 29. So I can use $userdb as long as it's in that particular if statement. any clues?
Looking at your script, you have the first "if" statement using the "#". Then you have the second "if" statement using "$userdb" where $userdb is assigned a value, then the third "if" statement that does nothing. When you try to print the $userdb after that, it hasn't been assigned a value. At least that's the way I see it.
Last edited by dday; 03-25-2010 at 12:35 PM..
Reason: clarity
It is giving you an error because it hasn't been assigned a value when you try to print it below the "if" logic. If you move that second print statement outside the function, it should've been assigned while going through the logic. It's hitting the lines that don't include the $userdb entry in the config file and trying to print it anyway during the logic flow.
...
It works if I take out line 29. So I can use $userdb as long as it's in that particular if statement. any clues?
That's because of the combination of "my" and "use strict".
Take the simpler case first i.e. the one that does not have "use strict".
The keyword "my" makes the variable local to the block. A block is the pair of braces immediately encompassing the variable. So, if you declare a "my" variable inside an if block (with no nested braces further on), then it becomes local to that if block.
If you try to print that variable outside that if block, the value will be null.
See below:
Code:
$
$
$ cat -n blub1.pl
1 #!/usr/bin/perl
2 Config_Loader();
3 sub Config_Loader {
4 $_ = "ABC123XYZ";
5 if (/ABC(123)XYZ/){
6 my $x = $1;
7 print "1) x = $x\n";
8 }
9 print "2) x = $x\n";
10 }
$
$ perl blub1.pl
1) x = 123
2) x =
$
$
Note that the $x inside the if block has different scope than the $x outside the block.
Now, if you add the pragma "use strict", then it will force you to declare all variables in each scope with "my" keyword. Since the $x outside the if block has different scope than the one inside, the strict pragma views it as a different global variable, and throws the error, because it expects you to declare that variable with "my" as well.
See below:
Code:
$
$
$ cat -n blub2.pl
1 #!/usr/bin/perl
2 use strict; # added the "use strict" pragma
3 Config_Loader();
4 sub Config_Loader {
5 $_ = "ABC123XYZ";
6 if (/ABC(123)XYZ/){
7 my $x = $1;
8 print "1) x = $x\n";
9 }
10 print "2) x = $x\n";
11 }
$
$ perl blub2.pl
Global symbol "$x" requires explicit package name at blub2.pl line 10.
Execution of blub2.pl aborted due to compilation errors.
$
$
This is a compilation, and not a runtime error !
Now, you can declare the variable outside the if block with a "my" to shut up "use strict" pragma, but it's not gonna serve your purpose, since "my" is always local to the nearest braces. So, the "my $x" inside the if block was discarded as soon as the if block ended.
See below:
Code:
$
$
$ cat -n blub3.pl
1 #!/usr/bin/perl
2 use strict;
3 Config_Loader();
4 sub Config_Loader {
5 $_ = "ABC123XYZ";
6 if (/ABC(123)XYZ/){
7 my $x = $1;
8 print "1) x = $x\n";
9 }
10 my $x; # "use strict" will not complain now, but you'll not see the value either, because the $x at line 7 does not exist anymore.
11 print "2) x = $x\n";
12 }
$
$ perl blub3.pl
1) x = 123
2) x =
$
$
So, to fetch the value of $x outside the if block, you can do one of the following:
(1) Keep using "use strict" and declare $x outside the if block, or outside the subroutine i.e. give it global scope.
See below:
Code:
$
$ cat -n blub4.pl
1 #!/usr/bin/perl
2 use strict;
3 my $x;
4 Config_Loader();
5 sub Config_Loader {
6 $_ = "ABC123XYZ";
7 if (/ABC(123)XYZ/){
8 $x = $1;
9 print "1) x = $x\n";
10 }
11 print "2) x = $x\n";
12 }
$
$ perl blub4.pl
1) x = 123
2) x = 123
$
$
(2) Remove "use strict" pragma and use $x wherever you want.
See below:
Code:
$
$
$ cat -n blub5.pl
1 #!/usr/bin/perl
2 Config_Loader();
3 sub Config_Loader {
4 $_ = "ABC123XYZ";
5 if (/ABC(123)XYZ/){
6 $x = $1;
7 print "1) x = $x\n";
8 }
9 print "2) x = $x\n";
10 }
$
$ perl blub5.pl
1) x = 123
2) x = 123
$
$
(2A) If you are not using "use strict", you can still declare the variable if you want, with or without "my" -
Code:
$
$
$ cat -n blub6.pl
1 #!/usr/bin/perl
2 $x = "";
3 Config_Loader();
4 sub Config_Loader {
5 $_ = "ABC123XYZ";
6 if (/ABC(123)XYZ/){
7 $x = $1;
8 print "1) x = $x\n";
9 }
10 print "2) x = $x\n";
11 }
$
$ perl blub6.pl
1) x = 123
2) x = 123
$
$
(2B) but if you are declaring it with "my" ensure that it's scope is global -
Code:
$
$
$ cat -n blub7.pl
1 #!/usr/bin/perl
2 my $x;
3 Config_Loader();
4 sub Config_Loader {
5 $_ = "ABC123XYZ";
6 if (/ABC(123)XYZ/){
7 $x = $1;
8 print "1) x = $x\n";
9 }
10 print "2) x = $x\n";
11 }
$
$ perl blub7.pl
1) x = 123
2) x = 123
$
$
The change in your code would be thus -
Code:
$
$
$ cat -n blub.config
1 # blub.config
2 # profiles/
3 $userdb=profiles/
4 # ignore following line
5 $another=blah/
$
$
$ cat -n blub.pl
1 #!/usr/bin/perl
2 use strict;
3 use warnings;
4
5 my $config_file="blub.config";
6 my $userdb;
7
8 Config_Loader();
9 print "Outside the subroutine: userdb = ",$userdb;
10
11 sub Config_Loader {
12 open(CONFIG,"$config_file") or die("config file not found $config_file");
13 my @config=<CONFIG>;
14 close CONFIG;
15 foreach (@config) {
16 if ($_ !~ /#/){ # this is TRUE for 2 lines, and $userdb is not flushed, hence the "Outside..." line is printed twice
17 if (/\$userdb/){ # this is TRUE for 1 line, hence the "Inside..." line is printed once
18 my @a = split(/=/,$_);
19 $userdb = $a[1];
20 print "Inside the if condition: userdb = ",$userdb;
21 }
22 print "Outside the if condition: userdb = ",$userdb;
23 }
24 }
25 }
$
$ perl blub.pl
Inside the if condition: userdb = profiles/
Outside the if condition: userdb = profiles/
Outside the if condition: userdb = profiles/
Outside the subroutine: userdb = profiles/
$
$
And there are other ways as well, as shown with my test scripts above.
Thank you Tyler! I was going about that the wrong way. I kept trying to send and return the variable through the function or subroutine. ( I think that's how it would get done in C ). Is that possible too? returning the variable if my was declared in that subroutine? and still keeping that attribute?
I have reviewed many examples on-line about running another process (either PERL or shell command or a program), but do not find any usefull for my needs way. (Reviewed and not useful the system(), 'back ticks', exec() and open())
I would like to run another PERL-script from first one, not... (1 Reply)
Hi Chaps,
Im after some advise with a script i've written however doesnt appear to work how I would like.
Basically I have a perl script which sucessfully pulls an expect script to login to multiple nodes and obtain some output from the nodes (total number of nat ports that are in use... (0 Replies)
I have the need to load modules in a local directory. I am a perl new guy. When I test Net::SSH2, I get the following message. I did load the required libssh2.
Not sure where to go from here. Is there a way to test that libssh2 is loaded correctly ? (1 Reply)
hi all,
i need a help for the following query.
Thanks in advance for your valuable time.
i have a main.pl file which has a global variable declared as below.
our myVar=0;
call first.pl script from the main.pl script.
print the value of myVar (the value is still 0 and not 10.)
i have a... (1 Reply)
I don't fully understand variables in perl.
If we have a variable defined like this "my $number = 1" then this is called a lexical variable? But if you define this at the top of a script then why isn't it a global variable because it would be available throughout the file?
Sorry if this is... (1 Reply)
Hi,
I have a strange issue in my script.
When script is run from command prompt it runs fine,but when run from cron it exist with error message.
I narrowed down the issue and found that " use Mail::Sender;" is the culprit.
If I comment the statment the code runs fine in both command and... (9 Replies)
So I want to use this program that I have downloaded from: PaGE - Patters from Gene Expression
However, I am not sure how to actually get in to and run the program... I can log into the server, and was assuming I needed to get the "PaGE_5.1.6.pl" file into a folder some how, but not sure how to... (2 Replies)
Like class loader in java, can we make a function loader in shell script, for this can someone throw some light on how internally bash runs a shell script , what happenes in runtime ...
thanks in advance.. (1 Reply)
Can someone give me "the lecture" on why you shouldn't make all your varables global when programming in perl. I have been doing this but I have heard that it is not a good practice. (3 Replies)