I am trying print all the values of a database table on a webpage in a table format.I am using a perl file having .cgi extension.Whenever i try to run the code i get the error "global symbol requires explicit package name".The rows of the database table should be displayed onLoad but it's not happening..
I have tried a lot but can't understand whats wrong with the code..
Please Help..
Code of people.cgi file ..
#!/usr/bin/perl
use CGI;
use DBI;
use strict;
use warnings;
print "Content-type:text/html\r\n\r\n";
#$q = CGI->new;
#print $q->header;
my $dsn = "DBI:mysql:Demo:localhost"; # Data source name
my $username = "mint"; # User name
my $password = "MINT123"; # Password
my $dbh;
my $sth; # Database and statement handles
$dbh = DBI->connect($dsn, $username, $password);
$sth = $dbh->prepare("SELECT * from people");
$sth->execute();
print "<h1>ganesh</h1>";
print "<table >
<tr>
<th>ID</th>
<th>Name of People Involved</th>
<th>Position</th>
<th>Roles(A user can have multiple roles)</th>
<th>Notes</th>
</tr>";
while( $href = $sth->fetchrow_hashref ) {
print "<tr>";
print "<td>$$href{'id'}</td>";
print "<td>$$href{'name'}</td>";
print "<td>$$href{'pos'}</td>";
print "<td>$$href{'role'} </td>";
print "<td>$$href{'notes'}</td>";
#print "<td><input type='text' value=\"$$href{'display_name'}\" id =\"dis-$$href{'windows_id'}\" readonly> </td>";
#print "<td><input type='text' value=\"$$href{'email_id'}\" readonly> </td>";
print "</tr>";
}
print "</table>";
$sth->finish();
$dbh->disconnect();
Error Messages..
Global symbol "$href" requires explicit package name at people.cgi line 31.
Global symbol "$href" requires explicit package name at people.cgi line 34.
Global symbol "$href" requires explicit package name at people.cgi line 35.
Global symbol "$href" requires explicit package name at people.cgi line 36.
Global symbol "$href" requires explicit package name at people.cgi line 37.
Global symbol "$href" requires explicit package name at people.cgi line 38.
Execution of people.cgi aborted due to compilation errors.
The structure of my MYSQL table..It has 14 coloumns...It has no data inside it...
$href should be defined (usually with my for local/lexical variables) which puts it's scope inside while loop in this particular case.
while (my $href = $sth->fetchrow_hashref ) { .. }
Whenever you get a Perl warning or error that you don't understand, you should add use diagnostics to your code and Perl will give you more detail about the problem. In this case, it would have said:
You've said "use strict" or "use strict vars", which indicates that
all variables must either be lexically scoped (using "my" or "state"),
declared beforehand using "our", or explicitly qualified to say which
package the global variable is in (using "::")
Update: Some additions to answer the further question in the comments below.
If the column can contain NULLs, and you're going to be printing those columns then you're going to get "undefined value" warnings unless you do something about it.
The easiest fix is probably to clean up the hash as soon as you get it. I'd replace undefined values with empty strings using something like this at the top of the loop block:
$href->{$_} // '' for keys %$href;
I also note that you're using the ugly $$hash_ref{key} syntax. Not sure where you picked that up from, but it's generally accepted that $hash_ref->{key} looks cleaner.
Related
I have the following two dimensional array (file.txt):
Code Element Repetitions
AL Train 23
BM Car 30
CN Bike 44
From an input (Code) given by the user, I want to extract the
corresponding Element information.
Example input: BM
Example output:Car
I tried with this code but I do not know how to compare the input name with array content. Thank you a lot
#!/usr/bin/perl
use strict;
use warnings;
print("Type code: ");
my $code = <STDIN>;
chomp($code);
my #content;
if(!open(TABLET, "file.txt")){
die "Unable to open the file\n";
}
while(<TABLET>){
chomp;
push #content, [split / /];
}
foreach my $row ($content) {
if ($content{$code}) {
print "$content{$code}\n";
}
}
close(TABLET);
There are a few problems here. And they can mostly be found by adding use strict to your code. The vast majority of experienced Perl programmers will always start their programs with:
use strict;
use warnings;
as these additions will find a huge number of common mistakes that programmers are prone to make.
The first problem can't be found like that. It seems to be a typo. You split your input using split /;+/ but your input file seems to be delimited by whitespace. So change split /;+/ to just split.
Now let's add use strict to your code and see what happens.
$ perl 2d
Global symbol "$content" requires explicit package name (did you forget to declare "my $content"?) at 2d line 20.
Global symbol "%content" requires explicit package name (did you forget to declare "my %content"?) at 2d line 21.
Global symbol "%content" requires explicit package name (did you forget to declare "my %content"?) at 2d line 22.
Execution of 2d aborted due to compilation errors.
Although there are three errors listed here, the second and third ones are both the same. But let's start with the first. Line 20 in my program is:
foreach my $row ($content) {
But what's that $content variable? You don't use that anywhere else. I suspect it's a typo for #content. Let's change that and try again.
$ perl 2d
Global symbol "%content" requires explicit package name (did you forget to declare "my %content"?) at 2d line 21.
Global symbol "%content" requires explicit package name (did you forget to declare "my %content"?) at 2d line 22.
Execution of 2d aborted due to compilation errors.
Ok. That fixed the first problem, but I guess we now have to look at the repeated error. This is generated by lines 21 and 22, which look like this:
if ($content{$code}) {
print "$content{$code}\n";
Obviously, there's no mention of %content on either of those lines - so what's the problem?
Well, the problem is that %content is mentioned on both of those lines, but it's disguised as $content{$code} in both cases. You have an array called #content and you'd look up values in that array using syntax like $content[0]. The face that you're using {...} instead of [...] means that you're looking in %content, not #content (in Perl you're allowed to have an array and a hash - and also a scalar - all with the same name, which is always a terrible idea!)
But we can't just change $content{$code} to $content[$code] because $code is string ("BM") and array indexes are integers. I we need to rethink this from scratch and actually store the data in %content, not #content. And, actually, I think that makes the code simpler.
#!/usr/bin/perl -w
use strict;
use warnings;
print("Type code: ");
my $code = <STDIN>;
chomp($code);
my %content;
if (!open(TABLET, "file.txt")){
die "Unable to open the file\n";
}
while(<TABLET>){
chomp;
my #record = split;
$content{$record[0]} = \#record;
}
if (exists $content{$code}) {
print "$content{$code}[1]\n";
} else {
print "$code is not a valid code\n";
}
close(TABLET);
We can clean that up a bit (for example, by using lexical filehandles and the three-arg version of open()) to get this:
#!/usr/bin/perl
use strict;
use warnings;
print("Type code: ");
chomp( my $code = <STDIN> );
my %content;
open my $tablet_fh, '<', 'file.txt'
or die "Unable to open the file\n";
while(<$tablet_fh>){
chomp;
my #record = split;
$content{$record[0]} = \#record;
}
if (exists $content{$code}) {
print "$content{$code}[1]\n";
} else {
print "$code is not a valid code\n";
}
I'm currently working on a script which takes a file as an input. The input file looks like this:
ECHANTILLON GENOTYPE
CAN1 genotype1
CAN2 genotype1
CAN3 genotype1
EUG1 genotype2
EUG2 genotype2
EUG3 genotype2
EUG4 genotype2
What I want to do is to create a hash with:
a first key as the GENOTYPE column and
a second key called "sample" which would point to the "ECHANTILLON" column. Its value would thus give for example CAN1, CAN2...
Here is what my script looks like:
#!/usr/local/perl-5.24.0/bin/perl
use warnings;
use strict;
use Data::Dumper;
use feature qw{ say };
use Getopt::Long;
my $list_geno;
GetOptions("g|input=s"=>\$list_geno);
my %hash_geno_group;
open(GENOTYPED,"<$list_geno") or die ("Cannot open $list_geno\n");
while (defined(my $l1= <GENOTYPED>))
{
my #geno_group_infos = split(m/\t/,$l1);
next if ($l1 =~ m/^ECHANTILLON/);
chomp($l1);
my $sample_nm = $geno_group_infos[0];
my $sample_geno_group = $geno_group_infos[1];
push #{ $hash_geno_group{$sample_geno_group}{"sample"} },$sample_nm;
foreach $sample_geno_group (keys (%hash_geno_group)){
foreach $sample_nm (values %{$hash_geno_group{%{$sample_geno_group}{"sample"}}}){
print $sample_geno_group, "\t" , $sample_nm, "\n";
}
}
}
close(GENOTYPED);
exit;
I tried to check what returns the print of $sample_nm variable but it returns me as an error
Can't use string ("genotype1") as a HASH ref while "strict refs" in use at Test.pl line 27, "GENOTYPED" line 2".
Can anybody explain me please:
Why I do have this type or error;
How to get values from the 1st column. I'll need further to store them into another variable in order to compare them with the same values but from another input file.
Thanks !
Replace the line
foreach $sample_nm (values %{$hash_geno_group{%{$sample_geno_group}{"sample"}}}){
with
foreach $sample_nm (#{$hash_geno_group{$sample_geno_group}{"sample"}}){
$sample_geno_group is a key of the hash %hash_geno_group, ie. a string (genotype1 or genotype2 in your example). But when you do %{$sample_geno_group}, you are dereferencing it as if it were a hash reference, hence the error Can't use string as HASH ref ....
Furthermore, values %{ xxx } should be used to retrieve values of the hash referenced by xxx. But in your case, xxx (ie. $hash_geno_group{$sample_geno_group}{"sample"}) is a reference to an array, in which you inserted elements with the push ... two lines above. So #{ xxx } should be used to retrieve its elements (as I did in the fix I suggested).
Another suggestion: Use a variable declared with my instead of your bareword GENOTYPED (so for instance, open my $genotype, '<', $list_geno or die "Can't open '<$list_geno': $!").
The following code does not print the 'HASH' type. What is wrong with this code ?
#! /usr/bin/perl
$prices{'pizza'} = 12.00;
$prices{'coke'} = 1.25;
$prices{'sandwich'} = 3.00;
print ref($prices);
First of all, you should put use strict; and use warnings; at the top of your script (and do that for all the future Perl code as well). After doing so, you will see the following:
Global symbol "%prices" requires explicit package name at ./a.pl line 4.
Global symbol "%prices" requires explicit package name at ./a.pl line 5.
Global symbol "%prices" requires explicit package name at ./a.pl line 6.
Global symbol "$prices" requires explicit package name at ./a.pl line 7.
Execution of ./a.pl aborted due to compilation errors.
What it means is that you tried to use to separate variables: a %prices hash and a $prices scalar.
After fixing variable declaration using my %prices;, you can get a reference to your %prices hash as follows:
my $prices_ref = \%prices;
print ref($prices_ref);
From formal standpoint, the answer may be shorter:
ref($prices) would return 1 if $prices value were a reference to another variable or false otherwise.
ref($prices) is the first use of an undeclared variable $prices (previous lines refer to another undeclared variable - hash %prices).
The value of $prices is undef and ref($prices) is an empty string.
Probably, your idea was to write
$prices->{'pizza'} = 12.00;
$prices->{'coke'} = 1.25;
$prices->{'sandwich'} = 3.00;
print ref($prices);
I get the following error:
Use of uninitialized value $_ in concatenation (.) or string at checkfornewfiles.pl line 34.
when attempting to run the following code :
#!/usr/bin/perl -w
#Author: mimo
#Date 3/2015
#Purpose: monitor directory for new files...
AscertainStatus();
######### start of subroutine ########
sub AscertainStatus {
my $DIR= "test2";
####### open handler #############
opendir (HAN1, "$DIR") || die "Problem: $!";
########## assign theoutput of HAN1 to array1 ##########
my #array1= readdir(HAN1);
######## adding some logic #########
if ("$#array1" > 1) { #### if files exists (more than 1) in the directory #######
for (my $i=0; $i<2; $i++) {shift #array1;} ####### for i in position 0 (which is the . position) loop twice and add one (the position ..) get rid of them #######
MailNewFiles(#array1);
} else { print "No New Files\n";}
}
sub MailNewFiles {
$mail= "sendmail";
open ($mail, "| /usr/lib/sendmail -oi -t" ) ||die "errors with sendmail $!"; # open handler and pipe it to sendmail
print $mail <<"EOF"; #print till the end of fiEOF
From: "user";
To: "root";
Subject: "New Files Found";
foreach (#_) {print $mail "new file found:\n $_\n";}
EOF
close($mail);
}
#End
I am new to perl and I don't know what's going wrong. Can anyone help me ?
A few suggestions:
Perl isn't C. Your main program loop shouldn't be a declared subroutine which you then execute. Eliminate the AscertainStatus subroutine.
Always, always use strict; and use warnings;.
Indent correctly. It makes it much easier for people to read your code and help analyze what you did wrong.
Use a more modern Perl coding style. Perl is an old language, and over the years new coding style and techniques have been developed to help you eliminate basic errors and help others read your code.
Don't use system commands when there are Perl modules that can do this for you in a more standard way, and probably do better error checking. Perl comes with the Net::SMTP that handles mail communication for you. Use that.
The error Use of uninitialized value $_ in concatenation (.) or string is exactly what it says. You are attempting to use a value of a variable that hasn't been set. In this case, the variable is the #_ variable in your foreach statement. Your foreach isn't a true foreach, but part of your print statement since your EOF is after your for statement. This looks like an error.
Also, what is the value of #_? This variable contains a list of values that have been passed to your subroutine. If none are passed, it will be undefined. Even if #_ is undefined, foreach (undef) will simply skip the loop. However, since foreach (#_) { is a string to print, your Perl program will crash without #_ being defined.
If you remove the -w from #!/usr/bin/perl, your program will actually "work" (Note the quotes), and you'll see that your foreach will literally print.
I do not recommend you not to use warnings which is what -w does. In fact, I recommend you use warnings; rather than -w. However, in this case, it might help you see your error.
You have EOF after the line with foreach. It contains $_ which is interpolated here but $_ is not initialized yet because it is not in foreach loop. It is not code but just text. Move EOF before foreach.
But probably you would like
sub MailNewFiles {
$mail= "sendmail";
open ($mail, "| /usr/lib/sendmail -oi -t" ) ||die "errors with sendmail $!"; # open handler and pipe it to sendmail
local $"="\n"; # " make syntax highlight happy
print $mail <<"EOF"; #print till the end of fiEOF
From: "user";
To: "root";
Subject: "New Files Found";
New files found:
#_
EOF
close($mail);
}
See perlvar for more informations about $".
The message
Use of uninitialized value $xxx in ...
is very straightforward. When you encounter it, it means that you are using a variable ($xxx) in any way, but that the variable has not ever been initialized.
Sometimes, adding an initialization command at the start of you code is enough :
my $str = '';
my $num = 0;
Sometimes, your algorithm is wrong, or you just mistyped your variable, like in :
my $foo = 'foo';
my $bar = $ffo . 'bar'; # << There is a warning on this line
# << because you made a mistake on $foo ($ffo)
I've got an hash array in my code, imported from the Config::General module that contains multiple levels of child hash arrays. I'm trying to access the variables within the hash array's child, yet it continually complains about variables being undefined.
If I try to define them as hash arrays in advance it complains that the contents are undefined. I'm clearly doing something stupid, are you able to point out what?
my $key;
my $val;
# allDevices should be a hash array istelf
my $allDevices = $cfgfile{'remote_hosts'}{'category:switch'}{'subcategory:brocade'};
while (($key, $val) = each $allDevices)
{
# This proves that the $val is a hash array also
INFO(" - $key => $val\n");
# This bit works ok
my #devDetails = split(/:/, $key);
my $thisDevice = $val;
my $thisDeviceType = $devDetails[0];
my $thisDeviceName = $devDetails[1];
INFO(" - Device Name: $thisDeviceName\n");
# This is where it complains - %thisDevice requires explicit package name
my $thisDeviceConnectProto = $thisDevice{'remote_device_connect_protocol'};
my $thisDeviceConnectIP = $thisDevice{'remote_device_connect_ipaddress'};
my $thisDeviceConnectUser = $thisDevice{'remote_device_connect_username'};
my $thisDeviceConnectPass = $thisDevice{'remote_device_connect_password'};
#########################################################################
# For each command specified in cli file #
#########################################################################
# CLI "for" loop
}
Thanks in advance
Don't forget to use strict and use warnings in your code. They helps you a lot in the compiling phase. For example:
# file: test.pl
use strict;
use warnings;
my $hash = {'one'=>1}; #hash reference
print $hash{'one'}, "\n"; #error: this refers to %hash, and it doesn't exists
print $hash->{'one'}, "\n"; #ok
The perl interpreter shows this error message:
Global symbol "%hash" requires explicit package name at test.pl line 7
You didn't declare %thisDevice hash and $thisDevice hashref is completely another variable.
Change
$thisDevice{'remote_device_connect_protocol'};
to
$thisDevice->{'remote_device_connect_protocol'};