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

hello again fellow monks

ive encountered a big problem. what i need to do is

  • 1)need to know if a regex failed or not
  • 2)need to know how many matches has regex hit
  • 3)need to know what errors are in $@ if the
  • regex failed
  • 4)need the program not to stumble if the regex failed
  • 5)the matches persist in memory from the last regex applied to the string,how can one clear those out,and know if the string really matched or not
  • 6)is there any alternative to $#- to see how much matches have been found ?
  • if i want all of these it seems i need to have the regex in an eval so that the program doesnt stop if the regex fails.if i want $@ i just use it but if its in an eval there will be no $@. if i want to see if the regex failed or not i can check like if($string=~/$regex/) {#succeded} but that looses my $@ and the matches array($1,$2,...) im pretty sure i need to use eval because i need to get the $@ wich i need to tell the user errors his regex caused. and i have tried sever combinations of the questions 2),3),4) and i have achieved only partial succes. i dont know what to do because i also have this problem with persistance of memory wich it seems i cannot fix easily because the matches variables are readonly(i would clear them out to be sure ive got a thing out of the way but i cant).

    what do you suggest doing ?

    how should i approach the problem?

    Replies are listed 'Best First'.
    Re: regex persistence of matches
    by blokhead (Monsignor) on Jun 18, 2007 at 18:43 UTC
      2)need to know how many matches has regex hit
      This statement could be interpreted different ways.. Do you want to know how many captures there were (i.e, $1, $2, ...)? Or do you want to see how many times the entire regex is matched globally in the string (i.e, as with m//g)? Judging from #6 above, you seem to mean the former.

      From perlop: In list context, m// returns:

      • the empty list if the match failed.
      • the list of all captures ($1, $2, ...) if the match succeeded and the regex contained a capture.
      • the singleton list (1) if the match succeeded but the regex did not contain a capture.

      This seems to give most of the information you need, with the catch that the last 2 cases overlap (i.e, "1" =~ /(1)/ and "foo" =~ /./ return the same thing in list context, but one has captures and one doesn't). To distinguish between these cases, you can look at @-, as you suggested. It will tell you whether there were captures in the last successful match, so you know how to interpret the return value of the match statement. Finally, to catch the case that the (user-provided) regex is invalid, you can wrap the whole thing in an eval.

      Putting it all together:

      use strict; my $string = "foobar1"; for my $regex (<DATA>) { chomp $regex; my ($success, @captures); eval { @captures = $string =~ /$regex/; $success = 1 if @captures; @captures = () if $success and @- == 1; }; print "$regex: "; if ($@) { print "invalid regex\n"; ## optionally print $@ here } elsif ($success and @captures) { print "matched: @captures\n"; } elsif ($success and !@captures) { print "matched (no captures)\n"; } else { print "didn't match\n"; } } __DATA__ foo((( (fo(o))(bar) o(.*)a foobar baz(bar)( blah(foo) (.)$
      Output:
      foo(((: invalid regex (fo(o))(bar): matched: foo o bar o(.*)a: matched: ob foobar: matched (no captures) baz(bar)(: invalid regex blah(foo): didn't match (.)$: matched: 1

      blokhead

    Re: regex persistence of matches
    by thezip (Vicar) on Jun 18, 2007 at 18:33 UTC

      You might try something like this:

      #!/perl/bin/perl -w use strict; my $str = 'ffggffffhhffii'; my $searchstr1 = 'ff'; my $searchstr2 = 'ee'; my @ary1 = $str =~ /$searchstr1/g; my @ary2 = $str =~ /$searchstr2/g; printf qq("%s" matches "%s" %d times.\n), $searchstr1, $str, scalar @a +ry1; printf qq("%s" matches "%s" %d times.\n), $searchstr2, $str, scalar @a +ry2; __OUTPUT__ "ff" matches "ffggffffhhffii" 4 times. "ee" matches "ffggffffhhffii" 0 times.

      Update: Ugh! First solution was borked... this version works better...

      Update2: Removed unnecessary parentheses from regex


      Where do you want *them* to go today?
    Re: regex persistence of matches
    by andreas1234567 (Vicar) on Jun 18, 2007 at 18:20 UTC
      I suggest you start with perlre and perlretut
      --
      print map{chr}unpack(q{A3}x24,q{074117115116032097110111116104101114032080101114108032104097099107101114})
    Re: regex persistence of matches
    by Anonymous Monk on Jun 18, 2007 at 18:32 UTC

      I also suggest you post some actual code so we know you have actually tried to solve the problem.