1

I am writing a program of pattern matching in perl ..but getting a error ..I have seen all the earlier posts regarding this matter but didn't find the solution...As I am new to perl So I am not getting exactly what is this error all about..

use of uninitialized value $line in string ne at line .. and in line ...

I am attaching here a perl file

use strict;

use warnings;

my $line = "";

open(OUTFILE, ">output.txt") or die ("cannot open file.\n");

if(open(file1,"match.txt") or die "Cannot open file.\n"){
    $line = <file1>;

    while ($line ne "") {
    if (defined($line) && (line =~ m/\sregion\s/i)) {
        print OUTFILE ("$line")};
        $line = <file1>;  # Problem Here
        if (defined($line) && ($line =~ /\svth\s/)) {
            print OUTFILE ("$line")
            };

        $line = <file1>;  # Problem Here
    }
}

My match.txt file contain this type of data..

Some text here

   region     Saturati   Saturati     Linear   Saturati   Saturati

    id        -2.1741m   -2.1741m   -4.3482m    2.1741m    2.1741m 

    vth     -353.9140m -353.9141m -379.2704m  419.8747m  419.8745m

Some text here  

Please solve the problem....thanks

Jim Davis
  • 5,241
  • 1
  • 26
  • 22

3 Answers3

1

If you can't read anything, your string will come back undefined... which is why you are seeing that message.

Also, probably better to check that you open input file first before creating an output file at all, so something like this:

open(INFILE,  "<match.txt")  or die "Cannot open input file";
open(OUTFILE, ">output.txt") or die "cannot open output file";

my $line;
while($line = <INFILE>){
    ...
}

Perl will end the loop if $line is undefined or an empty string.

ctschuster
  • 172
  • 3
  • See this for opening a file: http://stackoverflow.com/questions/318789/whats-the-best-way-to-open-and-read-a-file-in-perl – hmatt1 Feb 18 '14 at 04:45
  • You cannot do `while ($line)` only, you need `while ($line = )`. Also, you are opening `INFILE` but reading from `file1`. Your die statement should contain the error `$!`, and `open` should be three argument with lexical file handle `open my $fh, "<", $file or die "Cannot open: $!";` – TLP Feb 18 '14 at 05:08
1

The reason you are seeing those errors is that the variable $line contains undef. The reason it contains undef is that you assigned it a value from readline() (the <file1>) after the file had reached its end eof. This is described in perldoc -f readline:

In scalar context, each call reads and returns the next line until end-of-file is reached, whereupon the subsequent call returns "undef".

The reason you are encountering this error is that you are not using a traditional method of reading a file. Usually, you would do this to read a file:

while (<$fh>) {
    ...
}

This will iterate over all the lines in the file until it reaches end of file, after which, as you now know, the readline returns undef and the while loop is exited.

This also means that you do not have to check every other line whether $line is defined or empty. Moreover, you can combine your regexes into one, and generally remove a lot of redundant code:

while (<>) {
    if (/\b(?:region|vth)\b/i) {
        print;
    }
}

This is the core of the functionality you are after, and I am using some Perl idioms here: the diamond operator <> will read from the file names you give the script as argument, or from STDIN if no arguments are given. Many built-in functions use the $_ variable as default if no argument is given, which is what print does, and the while loop condition.

You might also note that I use word boundary \b instead of whitespace \s in the regex, and also use alternation | with non-capturing parentheses (?:...), meaning it can match one of those strings.

With this simplified script, you can do:

perl script.pl match.txt > output.txt

To provide your file names.

TLP
  • 66,756
  • 10
  • 92
  • 149
0

From the looks of it, it seems like you're trying to go through the match file and print all the lines that match region or vth to output.txt.

I simplified the code for you to do this:

use strict;
use warnings;

open(my $out_fh, ">", "output.txt") || die ("Cannot open file.\n");
open(my $file1, "<", "match.txt") || die ("Cannot open file.\n");

while( <$file1> ) {
    if ( /\s(region|vth)\s/i) {
        print $out_fh $_;
    }
}

This question goes into more detail about checking whether a variable is defined or empty: In Perl, how can I concisely check if a $variable is defined and contains a non zero length string?

Here is more information about opening files: What's the best way to open and read a file in Perl?

Community
  • 1
  • 1
hmatt1
  • 4,939
  • 3
  • 30
  • 51
  • This one is working now..thanks...but I want to know what was the error in my code... – user3318901 Feb 18 '14 at 05:51
  • Hey matt I also want to know what is the meaning of $_ in print line – user3318901 Feb 18 '14 at 05:57
  • Hey! `while(<$file1>)` will go through each line in the file, and inside the while loop, `$_` will be the value of that line. It basically replaces your variable `$line`. You could also use `while(my $line = <$file1>)` if you wanted to use the variable `$line` instead. – hmatt1 Feb 18 '14 at 06:00
  • I guess the main error in your code is that you want `my $line = <$file1>` inside the while statement, and you only need it once. You also don't really want to put `open` in an if statement. The error you were getting were from the lines you pointed out, and you don't need those lines anyway. – hmatt1 Feb 18 '14 at 06:05
  • one more thing is it possible to print the values occur only after pattern match....for example...after "region"..only "saturat saturat linear " and after "vth" only "x y z"....I dont want to print the strung region/vth....please suggest how to do....thanks.. – user3318901 Feb 18 '14 at 11:05
  • There are many ways to do that. You could use the line `s/(region|vth)//;` and put it inside the if statement, before you print it to remove those words. After you remove them you could remove the leading whitespace with `s/^\s+//;` You could also use `split` to convert the line into an array, and then print what you need from that. Here's a little tutorial: http://www.comp.leeds.ac.uk/Perl/split.html You can split on whitespace. – hmatt1 Feb 18 '14 at 15:49