Use of uninitialized value in concatenation (.) or string - perl

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.

Related

Unable to read the input file content that containing % sign

I am having simple open file input as showing below, which I have no problem reading the content from the input file, but not entirely readable.
open(IN,"<$modelRoot/Local_$project.pm") || die "ERROR\: $!";
while(<IN>)
{
$temp = $_;
chomp($temp);
printf "$temp\n";
}
The content that I printed out looks fine until the point that is a % sign.
This is the original input file content
my %LocalToolData = (
This is the content that I print out, it gives a warning too
Use of uninitialized value in printf at rfinteg_v4.pl line 846, <IN> line 24.
Use of uninitialized value in printf at rfinteg_v4.pl line 847, <IN> line 24.
my 0calToolData = (
Question: How do I read % sign from the input file and at the same time avoid having the warning?
printf does formatting using %, it's a reserved character. The first argument to printf is a template string, not any string.
You should be using print unless you want to make use of that feature.
You should not use printf with any content containing % unless you have corresponding placeholder values for that.
It even says in the documentation:
Don't fall into the trap of using a printf when a simple print would do. The print is more efficient and less error prone.

How can I extract specific columns in perl?

chr1 1 10 el1
chr1 13 20 el2
chr1 50 55 el3
I have this tab delimited file and I want to extract the second and third column using perl. How can I do that?
I tried reading the file using file handler and storing it in a string, then converting the string to an array but it didn't get me anywhere.
My attempt is:
while (defined($line=<FILE_HANDLE>)) {
my #tf1;
#tf1 = split(/\t/ , $line);
}
Simply autosplit on tab
# ↓ index starts on 0
$ perl -F'\t' -lane'print join ",", #F[1,2]' inputfile
Output:
1,10
13,20
50,55
See perlrun.
use strict;
my $input=shift or die "must provide <input_file> as an argument\n";
open(my $in,"<",$input) or die "Cannot open $input for reading: $!";
while(<$in>)
{
my #tf1=split(/\t/,$_);
print "$tf1[1]|$tf1[2]\n"; # $tf1[1] is the second column and $tf1[2] is the third column
}
close($in)
What problem are you having? Your code already does all the hard parts.
while (defined($line=<FILE_HANDLE>)) {
my #tf1;
#tf1 = split(/\t/ , $line);
}
You have all three columns in your #tf1 array (by the way - your variable naming needs serious work!) All you need to do now is to print the second and third elements from the array (but remember that Perl array elements are numbered from zero).
print "$tf1[1] / $tf1[2]\n";
It's possible to simplify your code quite a lot by taking advantage of Perl's default behaviours.
while (<FILE_HANDLE>) { # Store record in $_
my #tf1 = split(/\t/); # Declare and initialise on one line
# split() works on $_ by default
print "$tf1[1] / $tf1[2]\n";
}
Even more pithily than #daxim as a one-liner:
perl -aE 'say "#F[1,2]" ' file
See also: How to sort an array or table by column in perl?

Correct use of input file in perl?

database.Win.txt is a file that contains a multiple of 3 lines. The second of every three lines is a number. The code is supposed to print out the three lines (in a new order) on one line separated by tabs, but only if the second line is 1.
Am I, by this code, actually getting the loop to create an array with three lines of database.Win.txt each time it runs through the loop? That's my goal, but I suspect this isn't what the code does, since I get an error saying that the int() function expects a numeric value, and doesn't find one.
while(<database.Win.txt>){
$new_entry[0] = <database.Win.txt>;
$new_entry[1] = <database.Win.txt>;
$new_entry[2] = <database.Win.txt>;
if(int($new_entry[1]) == 1) {
chomp($new_entry);
print "$new_entry[1], \t $new_entry[2], \t $new_entry[0], \n"
}
}
I am a total beginner with Perl. Please explain as simply as possible!
I think you've got a good start on the solution. However, your while reads one line right before the next three lines are read (if those were <$file_handles>). int isn't necessary, but chomp is--before you check the value of $new_entry[1] else there's still a record separator at the end.
Given this, consider the following:
use strict;
use warnings;
my #entries;
open my $fh, '<', 'database.Win.txt' or die $!;
while (1) {
last if eof $fh;
chomp( $entries[$_] = <$fh> ) for 0 .. 2;
if ( $entries[1] == 1 ) {
print +( join "\t", #entries ), "\n";
}
}
close $fh;
Always start with use strict; use warnings. Next, open the file using the three-argument form of open. A while (1) is used here, so three lines at a time can be read within the while loop. Since it's an 'infinite' while loop, the last if eof $fh; gives a way out, viz., if the next file read produces an end of file, it's the last. Right below that is a for loop that effectively does what you did: assign a file line to an array position. Note that chomp is used to remove the record separator during the assignment. The last part is also similar to yours, as it checks whether the second of the three lines is 1, and then the line is printed if it is.
Hope this helps!

variable with multiple lines.delete first two lines in perl

I have a result of an sql query.it returns some 10 rows like below:
if i do the below in my perl script.
print $result
it gives me the output :
key value
----------- ------------------------------
1428116300 0003000
560779655 0003001
173413463 0003002
315642 0003003
1164414857 0003004
429589116 0003005
i just want to acheive that the first two lines to be deleted. and store the rest of each line in an array.
could any body please tell how do i achive this?
With something like :
my #lines = split /\n/, $result;
splice #lines,0,2;
Explanations :
split /\n/, $result is cutting your variable into an array of lines.
grep /^[\s\d]+$/ is filtering this array, and only keeps the elements that are a single line of spaces or digits (thus removing the first two lines)
Data-independent, little roundabout way: If you print $result out in a file, you can
use Tie::File;
tie #lines, Tie::File, $file or die "can't update $file: $!";
delete $lines[1];
delete $lines[2];
(untested)

Why doesn't die $template->error() show a line number?

In the following short program:
use Template;
my $template = Template->new (INCLUDE_PATH => ".");
$template->process ("non-existent-file")
or die $template->error ();
why doesn't die produce a line number and newline? My output looks like this:
~ 502 $ perl template.pl
file error - non-existent-file: not found ~ 503 $
Template is returning an error object of type Template::Exception. The object has overloaded stringification which applies when the value is printed, but when die looks at the value, it sees a reference and doesn't append the line number and newline. Force the value into a string earlier to fix the problem:
use Template;
my $template = Template->new (INCLUDE_PATH => ".");
$template->process ("non-existent-file")
or die '' . $template->error ();
prints
file error - non-existent-file: not found at scratchpad.pl line 25.
While #Eric's answer does solve the OPs issue, I suggest appending a space instead of pre-pending an empty string.
The reason is that if there are problems in the template, the error will be reported as coming from the template text instead of the line number in the perl file (which is what I want). See this short example:
use Template;
my $template = Template->new();
# Clearly a division by zero bug
$template->process(\"[% 1 / 0 %]")
or die $template->error();
This results in:
undef error - Illegal division by zero at input text line 1.
Which isn't very helpful. I want the perl file location. Instead I suggest:
my $template = Template->new();
$template->process(\"[% 1 / 0 %]")
or die $template->error() . ' ';
which produces:
undef error - Illegal division by zero at input text line 1.
at test.pl line 11.
This way I get the line number in the perl file too. It does look a little ugly, though. (You can stop reading now, if you like...)
An even more correct way would be:
use Template;
my $template = Template->new();
$template->process(\"[% 1 / 0 %]")
or do {
my $error = $template->error . '';
chomp $error;
die $error;
};
which produces this output:
undef error - Illegal division by zero at input text line 1. at t2.pl line 15.
But it is just so verbose and has a weird . in there. I've actually ended up creating:
sub templateError {
my ($template) = #_;
my $string = $template->error->as_string;
chomp $string;
$string =~ s/(line \d+)\.$/$1/;
return $string;
}
...
use Template;
my $template = Template->new ();
$template->process (\"[% 1 / 0 %]")
or die templateError($template);
So that I get this:
undef error - Illegal division by zero at input text line 1 at test.pl line 30.
as well as this for the OPs example:
file error - non-existent-file: not found at test.pl line 31.