perl: Scalar found where operator expected at script - perl

cannot find answer in Google, nor figure it out myself.
Win7 64bit
This is perl 5, version 22, subversion 3 (v5.22.3) built for MSWin32-x86-multi-thread-64int from Active State
with modules List::BinarySearch and PAR::Packer installed with cpan
Idea is to edit a text file and add numbers in sorted order. Below is a short version just to reproduce the problem.
Problem: binsearch_pos works when I run the script as pl but fails when I make a standalone EXE out of it.
Code to reproduce:
#!\usr\bin\perl
use strict;
use warnings;
use List::BinarySearch qw/binsearch_pos/;
my #numbers=(0,1,2,4,5,6);
print #numbers;
print "\n";
#numbers=searchandadd(\#numbers,3);
print #numbers;
#search right idx and add value
sub searchandadd {
my ($array, $add) = #_;
my #array = #{$array};
my #sorted = sort { $a <=> $b } #array;
my $idx = binsearch_pos { $a <=> $b } $add, #sorted;
if (0+#sorted == $idx) {
splice #sorted, $idx, 0, $add;
} else {
splice #sorted, $idx, 0, $add
if $sorted[$idx] ne $add;
}
return #sorted;
}
Expected output (from test.pl currently):
C:\Users\timo>test.pl 012456 0123456
EXE creation:
pp -o test.exe test.pl
EXE output:
C:\Users\timo>test.exe
Scalar found where operator expected at script/test.pl line 17, near "} $add"
(Missing operator before $add?) syntax error at script/test.pl line 17, near "} $add" Global symbol "$idx" requires
explicit package name (did you forget to declare "my $idx"?) at
script/test.pl line 18. Global symbol "$idx" requires explicit package
name (did you forget to declare "my $idx"?) at script/test.pl line 19.
Global symbol "$idx" requires explicit package name (did you forget to
declare "my $idx"?) at script/test.pl line 21. Global symbol "$idx"
requires explicit package name (did you forget to declare "my $idx"?)
at script/test.pl line 22.
I get same error when EXE made with perl2exe or pp. Could this be because there is some other version of binsearch_pos lurking somewhere?
I'm lost.
BR,
Timo

Related

Use of uninitialized value $e2 in string eq & find: warning:

Hopefully you can help a scientist to decipher whats wrong with the code I'm trying to run to clean up some NGS results. The Perl file itself comes from https://github.com/mtokuyama/ERVmap, though I am posting the code below for reference. The other Perl files in the package work just fine and, while I have built a passing ability to use the linux terminal, Perl is a little beyond me.
The linux terminal I'm using is currently running: Ubuntu 16.04.6 LTS
This is the Perl code I'm trying to run using the following command line on linux as instructed by their GitHub page:
perl clean_htseq.pl ./ c c2 __
#!/usr/bin/env perl
#$Id: run_clean_htseq.pl,v 1.2 2015/03/02 17:24:35 yk336 Exp $
#
# create pbs file
#
use warnings;
use strict;
use File::Basename;
use POSIX;
my $dir = shift;
my $e1 = shift;
my $e2 = shift;
my $stop = shift;
die "$e1 eq $e2" if ($e1 eq $e2);
my $find = "find $dir -name \"*${e1}\"";
my $out = `$find`;
my #files = split(/\n/, $out);
for my $f (#files) {
my $o = $f;
$o =~ s/${e1}$/$e2/;
my $cmd = "./clean_htseq.pl $stop $f > $o";
print "$cmd\n";
system($cmd);
}
The first error that I had was that the _clean_htseq.pl_ wasn't found (line 30, already altered to solution) which i solved by adding the ./ in front of it and giving the software permission to use the script file.
My current issue with the code/command line is the following error:
Use of uninitialized value $e2 in string eq at ./clean_htseq.pl line 18.
find: warning: Unix filenames usually don't contain slashes (though pathnames do). That means that '-name ‘*./SRR7251667.c’' will probably evaluate to false all the time on this system. You might find the '-wholename' test more useful, or perhaps '-samefile'. Alternatively, if you are using GNU grep, you could use 'find ... -print0 | grep -FzZ ‘*./SRR7251667.c’'.
This has been tracked down to the "__" at the end of the command line, while i'm sure this is supposed to mean something to the script I removed it and resulted in the following error:
Use of uninitialized value $stop in concatenation (.) or string at clean_htseq.pl line 30.
./clean_htseq.pl ./SRR7251667.c > ./SRR7251667.c2
Use of uninitialized value $e1 in string eq at ./clean_htseq.pl line 18.
Use of uninitialized value $e2 in string eq at ./clean_htseq.pl line 18.
Use of uninitialized value $e1 in concatenation (.) or string at ./clean_htseq.pl line 18.
Use of uninitialized value $e2 in concatenation (.) or string at ./clean_htseq.pl line 18.
eq at ./clean_htseq.pl line 18.
An error occurs too when I remove the "." from "./" but it comes back with an error about not finding the _clean_htseq.pl_ file which is in the working directory.
Your problem seems to be here:
my $dir = shift;
my $e1 = shift;
my $e2 = shift;
my $stop = shift;
Outside of a subroutine, shift works on #ARGV—the array that holds the command line arguments. You shift four times, so you need four arguments:
perl clean_htseq.pl ./ c c2 __
You only seem to give it two, and $stop has no value (so you are giving it less than two):
./clean_htseq.pl $stop $f
You can't just remove arguments and hope things still work out. Likely you're going to have to look at the source to see what those things mean (which should motivate you as a scientist to use good variable names and document code—Best Practices for Scientific Computing).
A first step may be to set defaults. The defined-or operator does well here:
use v5.10;
my $dir = shift // 'default_dir';
my $e1 = shift // 'default_value';
my $e2 = shift // 'default_value';
my $stop = shift // 'default_value';
Or, you could just give up if there aren't enough arguments. An array in scalar context gives you the number of elements in the array (although it doesn't guarantee anything about their values):
die "Need four arguments!\n" unless #ARGV == 4;
There are various other improvements which would help this script, some of which I go through in the "Secure Programming Techniques" chapter in Mastering Perl. Taking unchecked user input and passing it to another program is generally not a good idea.

How to print rows information from two dimensional array in Perl?

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";
}

create my own max and explicit package name requires in perl

I'm not use to coding in perl (it's the first time) but I have to work on a small part of code who someone send me, but I have this error which seem to be a common error for newbie :
Global symbol "$x" requires explicit package name at globalAlgt.pl line 30.
Global symbol "$y" requires explicit package name at globalAlgt.pl line 30.
On the line 30 I have this :
my $max = ($x, $y)[$x < $y];
which seem to be a function max created. I think it's because there is use strict; in the code.
Can you explain me this error ?
Thank you !
That can be re-written as a function
my $max = sub { $_[ $_[0] < $_[1] ] };
which can then be invoked as
print $max->(3,5), "\n";
print $max->(5,3), "\n";
At least, that's what I understand by "define my own max" and "function max".
Or, you can just use List::Util::max.

execution of perl script

I am trying to run a perl script 'googly.pl' from the command line, and it is giving some errors. Here is the script and the errors. I have re-checked the script, but I am still unable to successfully run the script.
#!C:\Strawberry\perl\bin\perl.exe
# googly.pl
# A typical Google Web API Perl script
# Usage: perl googly.pl <query>
# Your Google API developer's key
my $google_key='';
# Location of the GoogleSearch WSDL file
my $google_wdsl = "C:/vhosts/phpcs5/GoogleSearch.wsdl";
use strict;
# Use the SOAP::Lite Perl module
use SOAP::Lite;
# Take the query from the command-line
my $query = shift #ARGV or die "Usage: perl googly.pl
<query>\n";
# Create a new SOAP::Lite instance, feeding it
GoogleSearch.wsdl
my $google_search = SOAP::Lite->service("file:$google_wdsl");
# Query Google
my $results = $google_search ->
doGoogleSearch(
$google_key, $query, 0, 10, "false", "", "false",
"", "latin1", "latin1"
);
# No results?
#{$results->{resultElements}} or exit;
# Loop through the results
foreach my $result (#{$results->{resultElements}}) {
# Print out the main bits of each result
print
join "\n",
$result->{title} || "no title",
$result->{URL},
$result->{snippet} || 'no snippet',
"\n";
}
Errors
Semicolon seems to be missing at C:/vhosts/phpcs5/googly.pl line 19.
Syntax error at C:/vhosts/phpcs5/googly.pl line 17, near "wsdl my "
Global symbol "$google_search" requires explicit package name at C:/vhosts/phpcs5/googly.pl line 17
Global symbol "$google_search" requires explicit package name at C:/vhosts/phpcs5/googly.pl line 19
Syntax error at C:/vhosts/phpcs5/googly.pl line 20, near "doGoogleSearch"
Execution of C:/vhosts/phpcs5/googly.pl aborted due to compilation errors.
my $query = shift #ARGV or die "Usage: perl googly.pl
<query>\n";
# Create a new SOAP::Lite instance, feeding it
GoogleSearch.wsdl
my $google_search = SOAP::Lite->service("file:$google_wdsl");
should be
my $query = shift #ARGV or die "Usage: perl googly.pl <query>\n";
# Create a new SOAP::Lite instance, feeding it GoogleSearch.wsdl
my $google_search = SOAP::Lite->service("file:$google_wdsl");

Error-global symbol requires explicit package name

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.