http://qs321.pair.com?node_id=1120388


in reply to Use of uninitialized value in pattern match (m//)

Your warnings are from lines 41 and 43, your code only has 31 lines... what happened with the rest?

What is that syslog function your are calling in line 11?

I think, the following addresses your main cause for the warnings:

In line 25 you are working on the wrong variable. You should use $line for your regex match; not $_. Your line 25 reads as (ignoring the error at the end): ($participant) = $_ =~ m{(.....)/};

I would use lexical filehandles and would use more localized variables.

edit2: I have to correct me completely on that regex line; sorry:

Your line 25 does a regex match on $participant, which is not defined yet. So there is a regex match against an undefined variable. Line 26 wants to print that undefined variable as well.

The correction still is to do the regex match on $line and store the result in $participant

edit: fixed error and rephrased regex, sorry

Replies are listed 'Best First'.
Re^2: Use of uninitialized value in pattern match (m//)
by chris01010 (Novice) on Mar 17, 2015 at 22:55 UTC
    Sorry, I removed some debug lines I had in the script which I removed before posting

    The current errors are:

    Use of uninitialized value in string at rowGrab.pl line 26.

    Use of uninitialized value in pattern match (m//) at rowGrab.pl line 25.

    syslog allowa errors to be written to Unix syslog

      Having that cleared, now you can concentrate on your regex issue in line 25 ;-)

      I thought about your code and there are some other topics:

      • use lexical filehandles and the three argument form of open; e.g. see: Perl Maven - Open files in the old way
      • avoid "global" variables; e.g. if you need them only as loop variables; use the smallest scope possible; e.g. no my $i; for $i ( ...); better: for my $i ( ... )
      • Shouldn't you print $participant only if the regex match was successful
      • maybe you can use glob() to find the wanted files?

      Here's an untested rewrite based upon these ideas:

      #!/usr/bin/perl # http://perlmonks.org/?node_id=1120387 use strict; use warnings; my $log_dir = '/home/user1'; my $log_file = "$log_dir/trans.log"; my $trans_dir = '/data/directoy1'; # Log handles if ( not open my $loghandle, ">>", $log_file ) { # lexical hand +le and three argument form of open() # syslog ... # what's this? die "Cannot open file $log_file: $!"; } # maybe instead of opendir ... and readdir ... my @files = grep { -f } glob( "$trans_dir/*OT*" ); foreach my $file (@files) { print STDERR "File: $file\n"; print "$file\n"; open my $fh, "<", $file # same here; l +exical file handle and 3-arg-form of open() or die "Cannot open $file: $!"; while ( my $line = <$fh> ) { if ( (my $participant) = $line =~ m{(.....)/} ) { # expl +icitely use $line for regex print "$participant"; # only + print when match was found } } close $fh; }

        Thanks Linuxer, you adaption worked a treat (inluding glob)

        Just so people know I have only been on a 3 day course and I am "self teaching" the rest. So I really do appreciate the assistance and suggestions

        That being said :0), I am now moving the script on so that it reads each line and tries to match 2 values, both of which can be either one value or another

        I.E the first value can be 7722 or 59001 (appearing before the first occurence of /) and the second value can be N or U or C (which is the 362 character on the line)

        Once it matches both it should print the line, if not skip past it.

        I've had a go, but once again getting an error

        #!/usr/bin/perl # http://perlmonks.org/?node_id=1120387 use strict; use warnings; my $log_dir = '/home/smithc'; my $log_file = "$log_dir/trans.log"; my $trans_dir = '/data/FSA_Retrieval'; # Log handles if ( not open my $loghandle, ">>", $log_file ) { # lexical hand +le and three argument form of open() # syslog ... # what's this? die "Cannot open file $log_file: $!"; } # maybe instead of opendir ... and readdir ... my @files = grep { -f } glob( "$trans_dir/*OT*" ); foreach my $file (@files) { print STDERR "File: $file\n"; print "$file\n"; open my $fh, "<", $file # same here; l +exical file handle and 3-arg-form of open() or die "Cannot open $file: $!"; while ( my $line = <$fh> ) { if (/(7722/|59001/)/ && /.{361}(N|U|C)/) { print; } } close $fh; }

        When I run a perl -c against the script I get the compile error

        Unmatched ( in regex; marked by <-- HERE in m/( <-- HERE 7722/ at test2.pl line 37

      Those are actually warnings - the script keeps running, and probably does what you intended overall (whereas an error would cause the script to halt immediately). I expect that the warnings happen on the last iteration of the "for" loop:
      for $line (<FILE>) {
      The part in parens produces an anonymous array that the "for" will iterate over, and the last element of that array the "undef" element from the last attempt to read from the file handle and encountering 'eof'. If you used a while loop instead, you wouldn't enter the block (lines 25 and 26 would not be reached) on that last attempt to read from the file.

        The part in parens produces an anonymous array that the "for" will iterate over, and the last element of that array the "undef" element from the last attempt to read from the file handle and encountering 'eof'. If you used a while loop instead, you wouldn't enter the block (lines 25 and 26 would not be reached) on that last attempt to read from the file.

        um, none of that :) if the match fails $participant is undef , when you try to print var which is undef you get uninitialized warning

        $ perl -MData::Dump -we " open $fake, q{<}, \qq{a\nb\nc\n\n}; for(<$fa +ke>){ dd($_); }" "a\n" "b\n" "c\n" "\n"