I got the following Perl script that prints the content of the files in a directory:
#!/usr/bin/perl -w
use strict;
use warnings;
use Text::Autoformat;
my $NER = "$ARGV[0]/Data/NER_$ARGV[1]";
foreach my $fp (glob("$NER/*")){
if (-s $fp){
# Open file to read
open my $fz, "<", $fp or die;
binmode $fz, ":encoding(UTF-8)";
while(my $row = <$fz>){
chomp($row);
print "$row\n";
}
close $fz or die;
}
}
The script runs OK but there is this warning every time a new file is opened:
Use of uninitialized value in join or string at /usr/local/share/perl5/Text/Autoformat/Hang.pm line 182, <$fz> line 1.
Use of uninitialized value in join or string at /usr/local/share/perl5/Text/Autoformat/Hang.pm line 182, <$fz> line 1.
Use of uninitialized value in join or string at /usr/local/share/perl5/Text/Autoformat/Hang.pm line 182, <$fz> line 1.
Use of uninitialized value in join or string at /usr/local/share/perl5/Text/Autoformat/Hang.pm line 182, <$fz> line 1.
Use of uninitialized value in join or string at /usr/local/share/perl5/Text/Autoformat/Hang.pm line 182, <$fz> line 1.
Use of uninitialized value in join or string at /usr/local/share/perl5/Text/Autoformat/Hang.pm line 182, <$fz> line 1.
Use of uninitialized value in join or string at /usr/local/share/perl5/Text/Autoformat/Hang.pm line 182, <$fz> line 1.
Use of uninitialized value in join or string at /usr/local/share/perl5/Text/Autoformat/Hang.pm line 182, <$fz> line 1.
...
This is an example of the files that are being printed:
22-22 today DATE
25-25 NY LOCATION
Is this a bug in the Text::Autoformat module?
What you observe is normal and also you asked for it: the -w option switch enables global warnings.
You're supposed to just use the lexical warnings (pragma use warnings) in Perl 5.6 and later, so remove the option switch.
Related
I have a Perl hash (from some legacy code) but am unable print out the the keys.
if (ref $val eq ref {}) {
print "Keys: " . keys $val . "\n";
e.g. here's the output I get:
VAL: HASH(0x7ff0898eda70)
Type of argument to keys on reference must be unblessed hashref or arrayref
I've read this Type of argument to keys on reference must be unblessed hashref or arrayref but not sure how to apply it in this case.
Is there a way of fixing this?
====
UPDATE
I've also tried:
print "Keys: " . keys %$val . "\n";
but still get Type of argument to keys on reference must be unblessed hashref or arrayref
UPDATE 2
I can see I have the key a_key but I'm unable to print out its values. E.g. debugging with Carp::REPL I get:
$ print $val;
1$ HASH(0x7fb1e0828f00)
$ print %$val;
1$ a_keyARRAY(0x7fb1e0828e28)
$ print %$val{'a_key'}
Compile error: syntax error at (eval 412) line 63, near "$val{"
BEGIN not safe after errors--compilation aborted at (eval 412) line 63, <FIN> line 6.
$ print $val{'a_key'}
Use of uninitialized value in print at (eval 413) line 63, <FIN> line 7.
1
UPDATE 3
Using Data::Dumper in the REPL I get:
$ print Dumper( $val );
$VAR1 = {
'a_key' => [
'long_value'
]
};
1$ print Dumper( %$val );
$VAR1 = 'a_key';
$VAR2 = [
'long_value'
];
1$ print %$val[1]
Compile error: syntax error at (eval 450) line 63, near "$val["
BEGIN not safe after errors--compilation aborted at (eval 450) line 63, <FIN> line 44.
$ print %$val{'a_key'}
Compile error: syntax error at (eval 451) line 63, near "$val{"
BEGIN not safe after errors--compilation aborted at (eval 451) line 63, <FIN> line 45.
$ print $val[1]
Use of uninitialized value in print at (eval 452) line 63, <FIN> line 46.
First of all, you have a precedence problem. You are doing
keys($val . "\n")
instead of
keys($val) . "\n"
Secondly, the syntax for keys[1] is
keys HASH
meaning you need
keys(%$val)
Finally, you are calling keys in scalar context, which returns the number of keys in the hash. Call it in list context to get the keys of the hash. For example,
say "Keys: ", join ", ", keys(%$val);
There were a few versions where Perl experimented with allowing keys $ref, but the experiment was discontinued in 5.24. Avoid that!
I would like to know how to remove a key from a hash of array.
Given the following file as a simple example, forth column is always the third column in the paired match and data in not sorted.
....
NS501570 WWW 3009824 3009848
....
NS501572 WAD 3009848 3009898
....
I would like to collapse it into
NS501570 WWW 3009824 3009848 NS501572 WAD 3009848 3009898
I wrote the following code. I selected third column as key for hash. therefore I print the values from the first entry and column 4 would be the key of the other one:
use warnings;
use strict;
my $seq;
while(<>){
chomp;
my #line = split;
$seq->{"$line[2]" } = [#line];
}
foreach my $s (keys %{$seq} ) {
### #{ $seq->{$s}}[3] key for the second pair
print #{ $seq->{$s}}[0],"\t",#{ $seq->{$s}}[1],"\t",#{ $seq->{$s}}[2],"\t",#{ $seq->{$s}}[3],"\t",#{ $seq->{#{ $seq->{$s}}[3]}}[0],"\t",#{ $seq->{#{ $seq->{$s}}[3]}}[1],"\t",#{ $seq->{#{ $seq->{$s}}[3]}}[2],"\t",#{ $seq->{#{ $seq->{$s}}[3]}}[3],"\n";
delete ${$seq}{#{ $seq->{$s}}[3]};
}
it works but there is a small problem!
I do no know how to delete the second key (in this case 3009848 in the second entry) without getting the following error:
NS501570 WWW 3009824 3009848 NS501572 WAD 3009848 3009898
Use of uninitialized value in hash element at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in hash element at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in hash element at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in hash element at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in print at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in print at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in print at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in print at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in print at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in print at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in print at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in print at find_mate2.pl line 22, <> line 2.
Use of uninitialized value in delete at find_mate2.pl line 23, <> line 2.
It looks like you are deleting 3009848 before the 3009848 key is iterated in the foreach loop. You can probably try a simple next unless defined $seq->{$s}; since you've deleted $s==3009848 on the interation for 3009824. defined checking never hurts...
The warnings are due to the fact that you are deleting elements of your hash while you are iterating over them, which is in general, a bad idea.
Perl is warning you that you are trying to print something that is no longer there. Also, be aware that the keys are returned in random order unless you sort them.
Take a look at:
How should I delete hash elements while iterating?
I have just beginner in perl and write small piece of code.After Adding \n, I am getting the below error.Please find the table format below.I am trying to fetch ( 2 and 3 column)
from temp.txt after index.I am trying to ingnore first two line.
As I mentioned,I got error when I add \n into code
Error : Use of uninitialized value in concatenation (.) or
string at temp.pl line 10, <$fh2> line 300.
#! /usr/bin/perl
use strict;
use warnings;
my #data;
open(my $fh2,'<',"temp.txt") or die "Could not open file";
while(my $line =<$fh2>){
#data =split(/\s+/,$line);
print "$data[2] $data[3]";
print "\n";
}
Table format is:
$DATA1 SOURCE='XtA' VERSION='G-2014.06'
.TITLE '%curve%'
index temp1 temp2 temp3
alter#
1 -1.5750000e+00 -3.2053667e+00 -4.0000000e+01
1.0000000e+00(temp4)
2 -1.5272727e+00 -2.9323414e+00 -4.0000000e+01
1.0000000e+00
3 -1.4795454e+00 -2.6579232e+00 -4.0000000e+01
1.0000000e+00
....................................upto 99
temp1 temp2
<val1> <val2>
After you split do:
if (scalar(#data)==4) {
THEN YOUR PRINT CODE
}
Because you don't know if $data[3] or $data[2] exists.
You need to give us the full error. You should edit the question and then cut and paste the exact error, including the line number. Then, tell us what line in the file that is.
Chances are that in some of the data in that file there are fewer than 4 fields. Therefore, the split returns 3 or fewer scalars into #data. Then, when you try to refer to $data[3], that's an uninitialized value.
I have written a perl script to merge the gcov files from different machines.
Below is the subroutine i have written for merging.
sub merge_gcov()
{
open(FILE1, "<$_[0]") or die "can not open file";
open(FILE2, "<$_[1]") or die "can not open file";
open(FILE3, ">$_[2]") or die "can not open file";
my ($line1, $line2 , $flag );
while ( 1 )
{
$line1 = <FILE1>; # read them each
$line2 = <FILE2>;
last unless ( $line1 || $line2 ); # if both empty exit loop
#
# otherwise test for which one just finished
#
unless( $line1 )
{
$flag = 1;
last;
}
unless( $line2 )
{
$flag = 2;
last
}
#
# now do the voodo on the two lines
#
chomp($line2);
chomp($line1);
if($line1=~/^\s*-/ and $line2 =~/^\s*-/)
{
print FILE3 "$line1\n";
}
elsif($line1=~/^\s*#####/ and $line2 =~/^\s*#####/)
{
print FILE3 "$line1\n";
}
elsif($line1=~/^\s*#####:\s{0,}(\d{1,})/ and $line2 =~/^\s{0,}(\d{1,})/)
{
print FILE3 "$line2\n"
}
elsif($line1=~/^\s{0,}(\d{1,})/ and $line2 =~/^\s*#####:\s{0,}(\d{1,})/)
{
print FILE3 "$line1\n"
}
elsif($line1=~/^\s{0,}(\d{1,})/ and $line2 =~/\s{0,}(\d{1,})/)
{
my #values1 = split(/:/, "$line1");
my #values2 = split(/:/, "$line2");
print FILE3 (" ",$values1[0]+$values2[0]),":","$values1[1]:","$values1[2]\n";
}
else
{
print FILE3 "$line1\n";
print FILE3 "$line2\n";
}
}
close(FILE3);
}
Merging is done properly but after merging i am getting below error....
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 284046 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 284414 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 302995 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 311633 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 311962 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 321536 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 323445 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 329553 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 336009 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 336330 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 338188 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 343170 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 349037 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 349610 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 633937 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 634509 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 634877 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 653458 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 662096 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 662425 (#1)
Use of uninitialized value in concatenation (.) or string at
./Merge_gcov_generalised.pl line 226, <FILE2> line 671999 (#1)
Use of uninitialized value in concatenation (.) or string at
I know i don't get these warnings when i used no warnings,But is there any other way to remove these warnings.
Line 226 is :print FILE3 (" ",$values1[0]+$values2[0]),":","$values1[1]:","$values1[2]\n";
If all you want to do is get rid of that particular warning that you already expect and have accounted for, then all you have to do is this:
{ no warnings 'uninitialized';
# **Small** bit of code causing the problem.
say "A string and $probably_undefined";
}
The reason I stress, small code is that Perl does not have a thousand warning categories to turn on and off by pragma. It has several rather broad categories that if you leave disarmed for too large a space will bite you. The idea is to look at each warned condition and decide if an uninitialized value has no effect--or one that you can at least account for.
You test for one or the other of the lines being uninitialized but you never use that information, so you're printing an undef concatenated with a newline in your final else; this is the source of your warnings.
Your gcov files actually have a bunch of excess newlines in them, caused by one file running out first, one per each unmatched line. They're only valid because gcov is either very forgiving in what it accepts, or because gcov stops reading the input silently when it sees the first bare newline. The first is great; the second is very bad.
To fix this, we need to figure out where we expect to have an undef and what to do when we find one. This code can generate undef in $line1 and $line2 when we hit the end of each file. Let's look at how you use these to see where undef is OK and where it's not.
Testing for both lines being false (e.g., undef): this is a good use of undef.
Setting $flag: good usage, but bad logic, since you never use $flag again.
Pattern matches: good usage, because pattern matches against nothing should (and do) fail, and this is correct for your code.
Printing a line that might be undef: bad usage, as this will generate your warning and output an extra empty newline.
Because the pattern matches will all fail against an undef, you can just skip the code that sets $flag altogether and make the last else look like this:
...
else {
# One or the other file has run out already. Note that
# the $line variables being undef here is OK because that's
# an expected possible value that we're actually testing for.
# We could used "defined $lineX" but since undef itself is
# false, this is okay.
print FILE3 "$line1" if $line1;
print FILE3 "$line2" if $line2;
}
Now for some undef philosophizing.
An uninitialized variable warning is almost always a logic error somewhere, despite Perl being nice about fixing it up. If you are getting these, you should look for the following:
Am I calling something that is returning an undef? If so, am I calling it wrong, or with bad parameters? Can I substitute a default value without it being erroneous, like 0 or '' (using the defined-or // operator), if my call is valid? Do I need a table or sub to give me default values instead? If I can't use a default value, what's wrong with my logic?
If that's not the case, am I referencing an uninitialized array or hash entry? Perl will auto-vivify those entries and set them to undef. Is my index or key bad? If not, should I be setting those entries to a default value myself, bounds-checking my index for an array, or checking if the hash element exists for a hash? Otherwise the criteria in 1. apply.
If neither of those is the case, I have an uninitialized scalar variable. Why isn't it initialized? What should I have initialized it to? What assumption did I forget to make (by not initializing the scalar to a known value)?
Generally speaking, unless your code is supposed to issue a warning (e.g., you added a warn to it), a warning means something isn't as you expected it to be. You should look at that and see why, not just hide the diagnostic.
We have some code which catches an exception, logs the message and then calls Carp::longmess to get the stacktrace.
So a simplified view of what we are doing is:
eval { <some SOAP::Lite stuff> };
if( my $err = $# )
{
logwrite( "Caught Error: $err" );
}
The logwrite function is essentially:
sub logwrite($)
{
my $msg = $_[0];
my($pkg,$fil,$lin)=caller;
my $timestamp = POSIX::strftime(...);
print STDERR "$timestamp $fil/$lin $msg\n";
print STDERR "$timestamp $fil/$lin Stack trace:\n" . Carp::longmess . "\n";
}
But in the log I am seeing:
20111030 Module.pm/42 Caught Error: at line
Use of uninitialized value in caller at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 22.
Use of uninitialized value in string eq at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 91.
Use of uninitialized value in numeric lt (<) at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 200.
Use of uninitialized value in pattern match (m//) at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 55.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 55.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 142.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 142.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 142.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/5.8.8/Carp/Heavy.pm line 142.
...
And that sequence of warnings from the Carp/Heavy.pm module repeats over and over again indefiniately, blowing out the logifle. So we eventually kill it off. These warnings look like they're being triggered by the call to Carp::longmess. The other intersting thing here is the $# variable appears to just be at. It as the at added by die, but no actual error message or line number.
Has anyone seen this before or have any idea what's coing on with the Carp package? This is rare, but has happenned a handful of times over the past month or so, and we have hundreds of these jobs running every day.
Your code works for me on perl v5.10.1, with Carp.pm version 1.11.
However, note that what it does is perhaps not what you expect: the backtrace produced by longmess will show where the logwrite function was called from, not where the actual error occurred inside the eval.
I realize this doesn't answer your actual question, but . . . since apparently $msg eq 'at line ' in this case, maybe you should just bypass the issue by tacking unless $msg eq 'at line ' onto the end of the print ... Carp::longmess ... statement? (I mean, unless someone proposes a real solution.)