curtisb has asked for the wisdom of the Perl Monks concerning the following question:

OK, I have this code
#!/usr/bin/perl -w print "\nWhat file would you like to open: "; $file = <STDIN>; print "\nAttempting to open $file\n"; open(FILE, "< $file") || die "Unable to open file: $file\n"; while(<FILE>) { if($text = "go") { $text =~ s/^go/\//g; $count++; } } print "There are $count lines in this file\n"; close(FILE) || die "Unable to close file: $file\n";
I can't seem to get the matching right somewhere. The errors I'm getting are as follows.
C:\perl>perl test.pl
What file would you like to open: go.txt
Attempting to open go.txt
Use of uninitialized value in pattern match (m//) at test.pl line 10, <FILE> line 1.
Use of uninitialized value in pattern match (m//) at test.pl line 10, <FILE> line 2.
Use of uninitialized value in pattern match (m//) at test.pl line 10, <FILE> line 3.
Use of uninitialized value in pattern match (m//) at test.pl line 10, <FILE> line 4.
Use of uninitialized value in pattern match (m//) at test.pl line 10, <FILE> line 5.
Use of uninitialized value in concatenation (.) or string at test.pl line 16, <FILE> line 5.
There are lines in this file
Could someone point me in the right direction.
Thanks,
Bobby

Replies are listed 'Best First'.
Re: Matching Question
by Zaxo (Archbishop) on Sep 20, 2002 at 18:49 UTC

    $text is the ininitialized variable. It isn't set to anything, ever. Warnings and strict would have been helpful to you. I think you want: s/^go/\//g and $count++ while(<FILE>);The way you coded that, $count is the number of substitutions, not the number of lines in the file.

    I also think you want to chomp the filename you get from STDIN.

    After Compline,
    Zaxo

Re: Matching Question
by dws (Chancellor) on Sep 20, 2002 at 18:35 UTC
    If you add   use strict; then the problem might jump right out at you.

    Actually, though, you have several problems. One of which is that   $text = "go" is an assignment, not a test, and not the right test for strings. Fix that, and the problems that strict reports, and you'll be a lot closer to solving this yourself.

Re: Matching Question
by thelenm (Vicar) on Sep 20, 2002 at 18:35 UTC
    Are you trying to replace "go" with "/" on lines that start with "go"? If so, you should be matching against $_, not $text. Also, you never use $text after you do the substitution... if you want something useful, you should do something, like print the line. This probably doesn't do exactly what you want, but here's my best shot:
    # print each line after replacing "go" with "/" while (<FILE>) { $count++ if s/^go/\//; print; } print STDERR "There were $count lines starting with 'go' in this file\ +n";

    -- Mike

    --
    just,my${.02}

      OK, that worked, but how do I write it back to the same file?
      Bobby
        Hmmm... if this is the entire script, you could simply pass the filename as a parameter and use the -p and -i switches, something like this:
        #/usr/bin/perl -pi.bak $count++ if s/^go/\//; END { print STDERR "There were $count lines starting with 'go' in the +file\n"; }
        This will automatically overwrite your original file with the new, substituted lines. It will also create a backup file named "<file>.bak" just in case. :-)

        If this is not your entire program, then you can just capture its output to a new file, then rename the new file to have the same name as the old one. You could have your program do this itself by printing its output to a new file, then renaming that file. Maybe something like this (this is not the whole program, of course):

        open FILE, "< $file" or die "Can't open input file: $!\n"; open OUT, "> '$file.new'" or die "Can't open output file: $!\n"; while (<FILE>) { $count++ if s/^go/\//; print OUT; } close OUT; close FILE; print STDERR "There were $count lines starting with 'go' in the file\n +"; rename $file, "$file.bak"; # make backup copy rename "$file.new", $file; # overwrite original file

        -- Mike

        --
        just,my${.02}

Re: Matching Question
by Anonymous Monk on Sep 20, 2002 at 18:45 UTC
    As DWS mentioned earlier your $test comparison is actually an assignment operator.
    Try this instead:
    #!/usr/bin/perl -w print "\nWhat file would you like to open: "; chomp ($file = <STDIN>); print "\nAttempting to open $file\n"; open(FILE, "$file") || die "Unable to open file: $file\n"; while(<FILE>) { $text =~ $_; if($text eq "go"){ $text =~ s/^go/\//g; $count++; } } print "There are $count lines in this file\n"; close FILE;
    I hope this helps!
      Woops! change $text =~ $_; --> $text = $_;
      Thanks for the help. This is what I have now. But there is a small problem.
      #!/usr/bin/perl -w print "\nWhat file would you like to open: "; chomp($file = <STDIN>); print "\nAttempting to open $file\n"; open(FILE, "< $file") || die "Unable to open file: $!\n"; open(OUT, "> '$file.new'") || die"Unable to create new file: $!\n"; while (<FILE>) { $count++; $text = $_; if ($text eq "go") { $gocount++ if s/^go/\//g; print OUT; } } print "\nThere are $count lines in the file\n"; print "Go count equal $gocount\n"; close(OUT) || die "Unable to close OUT file: $!\n"; close(FILE) || die "Unable to close file: $!\n";

      It reads in 9 lines from the file. But only takes 1 go, changes it and writes that 1 to the new file. If I do a while $text eq "go" I get stuck in a loop. Have any clues. I need it to find every go in the file.

      Here is the sample file.

      go
      go
      go
      go
      sam
      it
      go
      go
      go

      Thanks for the help,
      Bobby
        you need every line to be cmop'ed $_="go\n" ... chomp() does it.
        ... while (<FILE>) { $count++; $text = $_; ## this is what you need chomp($text); ## this is what you need if ($text eq "go") { $gocount++ if s/^go/\//g; print OUT; ...
Re: Matching Question
by curtisb (Monk) on Sep 20, 2002 at 18:23 UTC
    Forgot one thing. I'm trying to replace "go" with a /.
    Thanks
    Bobby
Re: Matching Question
by Nemp (Pilgrim) on Sep 20, 2002 at 18:34 UTC
    Update: Doh, I misread $text = "go" as $text == "go" sorry !

    You don't seem to have initialized the value $text with anything at all here? Did you want it to contain the value from the line in the file? ( $text = $_ or foreach $text (<FILE>) )

    This is almost certainly the reason for the uninitialized value in pattern match errors, and hence the uninitialized in concatenation since $count is never initialized as $text is never defined.

    HTH,
    Neil