Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Use of uninitialized value when using regex

by PerlScholar (Acolyte)
on Sep 12, 2010 at 13:23 UTC ( [id://859845]=perlquestion: print w/replies, xml ) Need Help??

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

Hi All,
I'm getting the error: Use of uninitialized value in string at Z:/My Documents/Workspace/myscript.pl line 23 when trying to read something from a file
My file contains just one line: "Version=2010-09-01_17-29-04 Build=26" and i'm trying to get the last numbers i.e "26". Any ideas? Appreciate it thanks!

my $dir1 = 'Z:\My Documents\Workspace'
my $versionFile = "$dir1\\version.txt";

     open (VFILE, $versionFile)|| die $!;
     my $vdata= <VFILE>;
     close (VFILE);

     print "$vdata\n";

             (my $build)=($vdata=~/=(\d+)$/);
             print "$build";#this is the problem line

Replies are listed 'Best First'.
Re: Use of uninitialized value when using regex
by jethro (Monsignor) on Sep 12, 2010 at 13:59 UTC

    Your script works, I made sure by testing it with a sample file. Could it be that your version.txt has invisible control characters in it? You can find out by using Data::Dumper with $Data::Dumper::Useqq=1 to print $vdata

Re: Use of uninitialized value when using regex
by ww (Archbishop) on Sep 12, 2010 at 16:59 UTC

    Shorter (parentheses saved and used here); arguably 'more straightforward' or 'maintainable':

    my $txt="Version=2010-09-01_17-29-04 Build=26"; my ($build) = $txt =~ /(?:=)(\d+)$/; print $build;

    Output: 26

      More maintainable? You changed /=(\d+)$/ into /(?:=)(\d+)$/. How's that more straightforward or maintainable? What's the point of grouping a single character?
Re: Use of uninitialized value when using regex
by roboticus (Chancellor) on Sep 12, 2010 at 13:37 UTC

    Update: Just ignore this entire node, it's completely wrong. I'd like to blame it on answering before I finish my first cup of coffee, but in fact I just learned something new: the $ matches the end of line characters too, so my suggestion was entirely wrong. Thanks ++ to jethro for the catch, and I'm sorry for the hideously ugly node!

    PerlScholar:

    You're forgetting the end-of-line character(s). Try this:

    my ($build) = ($vadata =~ /=(\d+)\s*$/);

    ...roboticus

    Update: Fixed code, added parenthesis around $build. Thanks to Erez for pointing it out. An intermediate update was:

    You're forgetting the end-of-line character(s). Try this regex: /=(\d+)\s*$/

    Update: I replaced the node content, as it was simpler than trying to edit it to show differences between original and updated content.

      the expression $var =~ /regex/ returns a true or false value, not the captured value. The special variable $1 contains the value you captured in the parentheses, so you should use something along the following lines:

      my $build; if ($vadata =~ /=(\d+)\s*$/) { $build = $1; }
      and use $build only if it's not null.

      UPDATE: actually the OP was matching in list context, not scalar context, so a messed up answer. Please ignore and see above and below for a more enlightened discussion...

      "Principle of Least Astonishment: Any language that doesn’t occasionally surprise the novice will pay for it by continually surprising the expert..

        Hi Erez,

        In scalar context:

        my $build = ($vdata=~/=(\d+)$/);
        you're correct; you will get 0 or 1.  But in list context:
        (my $build) = ($vdata=~/=(\d+)$/);
        you will get the captured values.  For example:
        use strict; use warnings; my $text = "The quick brown fox jumps over the lazy dog"; my ($h, $i, $j) = $text =~ /(\S*h\S*).*?(\S*i\S*).*?(\S*j\S*)/; print "$h, $i, $j\n"; __END__ Output: The, quick, jumps

        Hi roboticus,

        I, too, thought this a simple case of not matching the newline.  However, I can't explain why I'm getting the following:

        use strict; use warnings; # my $dir1 = 'Z:\My Documents\Workspace'; # my $versionFile = "$dir1\\version.txt"; # open (VFILE, $versionFile)|| die $!; # my $vdata= <VFILE>; # close (VFILE); try_this("Version=2010-09-01_17-29-04 Build=26"); try_this("Version=2010-09-01_17-29-04 Build=26\n"); try_this("Version=2010-09-01_17-29-04 Build=26\n\n"); sub try_this { my ($vdata) = @_; print "=" x 69, "\n"; print "Str: [$vdata]\n"; printf "Asc: %s\n\n", join ' ', map { ord $_ } split //, $vdata; (my $build) = ($vdata=~/=(\d+)$/); print "Build = [$build]\n\n";#this is the problem line } __END__ Output: ===================================================================== Str: [Version=2010-09-01_17-29-04 Build=26] Asc: 86 101 114 115 105 111 110 61 50 48 49 48 45 48 57 45 48 49 95 49 55 45 50 57 45 48 52 32 66 117 105 108 100 61 50 54 Build = [26] ===================================================================== Str: [Version=2010-09-01_17-29-04 Build=26 ] Asc: 86 101 114 115 105 111 110 61 50 48 49 48 45 48 57 45 48 49 95 49 55 45 50 57 45 48 52 32 66 117 105 108 100 61 50 54 10 Build = [26] ===================================================================== Str: [Version=2010-09-01_17-29-04 Build=26 ] Asc: 86 101 114 115 105 111 110 61 50 48 49 48 45 48 57 45 48 49 95 49 55 45 50 57 45 48 52 32 66 117 105 108 100 61 50 54 10 10 Use of uninitialized value $build in concatenation (.) or string at D:\Documents and Settings\jonorton\a.pl line 25. Build = []

        The first string (no newlines) matches as expected, and the third (2 newlines) fails, also as expected.  But the second (1 newline) matches, despite the newline at the end.  I'm not sure what to make of that.

        This is on perl v5.10.0 for MSWin32-x86-multi-thread (Windows xp), binary build 1004 from ActiveState.


        s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: Use of uninitialized value when using regex
by PerlScholar (Acolyte) on Sep 12, 2010 at 18:03 UTC
    Thanks guys combined all your advice to get it working.
      I guess a bit off topic as you've gotten some good advice.. but I would recommend that you get out of the habit of using '\' in path names. This is just not necessary and this backslash the backslash stuff can get to be a mess!

      In ancient DOS days, the backslash was required. But now with the MS command line, that is no longer true. The \ character is the escape character in string evaluation and it just causes problems. Use the *nix style /, forward slash. Of course remember that when making a path name, put double quotes around the string "$a/$b" otherwise Perl will figure that you are doing division! But in general forego this \ stuff.

      #!/usr/bin/perl -w use strict; my $dir1 = 'Z:\My Documents\Workspace'; #you need single quote here my $versionFile = "$dir1\\version.txt"; print "$versionFile\n"; #Z:\My Documents\Workspace\version.txt my $dirA = "Z:/My Documents/Workspace"; #with / "" is no problem my $versionFileA = "$dirA/version.txt"; print "$versionFileA\n"; #Z:/My Documents/Workspace/version.txt
      Another tip for working with the command line, wild cards can be used like this: (not for use in a program, but for getting to where you want to go as a human without typing so much(
      C:\>cd do* C:\Documents and Settings>
        Thanks again Marshall :)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://859845]
Approved by Erez
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2024-04-19 04:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found