Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Error in my Regular expression pattern

by shajiindia (Acolyte)
on Mar 18, 2012 at 06:57 UTC ( #960264=perlquestion: print w/replies, xml ) Need Help??
shajiindia has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I am using the following code and it gives a wrong result when run. I am trying to figure out but could not get the reason. Please help.
$_ = "Twinkle twinkle little star"; $n = m/twinkle/ig; print "Number of occurences = $n\n"; while(/twinkle/ig) { $count++; } print "Found $count times\n";
When I run, it produces the following result

Number of occurences = 1
Found 1 times

but when I comment out lines 3 & 4 it gives the correct result. Why does the while loop produces the correct result when I comment out lines 3 & 4?

Found 2 times

Replies are listed 'Best First'.
Re: Error in my Regular expression pattern
by Anonymous Monk on Mar 18, 2012 at 07:13 UTC
      Like perlop#m/PATTERN/msixpodualgc ( perlop#m// ), says,
      m// in scalar context returns true if it succeeds, false if it fails.

      Each time m// succeeds against a variable, like when  $n = m/twinkle/ig; executes, position is changed, so that  while(/twinkle/ig) { executes, only the second twinkle is counted.

      If you add this to your program before the while loop

      print "pos is ", pos, ", remainder '", substr($_, pos), "'\n"; pos($_) = undef;
      this resets pos associated with $_, and then your program will produce
      Number of occurences = 1 pos is 7, remainder ' twinkle little star' Found 2 times

      Like perlfaq4 says, if you want the number of occurances, use the flying lentil operator, use  my $count =()= m/twinkle/ig;

Re: Error in my Regular expression pattern
by JavaFan (Canon) on Mar 18, 2012 at 12:52 UTC
    Consider this:
    • You have a deck of cards (52).
    • You remove the top card.
    • You deal the remaining cards among 4 players.
    • You end up one short.
    • Now, you collect all cards again.
    • This time, you don't remove the top card.
    • You deal the remaining card among the 4 players.
    Do you now wonder how it comes that if you don't remove the top card, you can deal 52 cards evenly, but you cannot if you do?

    That's the same what's happening here. There are 2 matches of twinkle in your string. If you first match one, then the rest, the "rest" only matches once. If you only match "the rest", you get both matches.

Re: Error in my Regular expression pattern
by NetWallah (Abbot) on Mar 18, 2012 at 15:48 UTC
    Here is the "canonical" way of counting matches into a scalar:
    ~$ perl -e 'my $x=()="Twinkle twinkle little star"=~/twinkle/ig; print + qq|$x\n|' 2
    Note the use of () as an intermediate to switch between scalar and list contexts.
    I Sympathize because I too had trouble wrapping my head around this.

                 All great truths begin as blasphemies.
                       ― George Bernard Shaw, writer, Nobel laureate (1856-1950)

Re: Error in my Regular expression pattern
by Marshall (Abbot) on Mar 18, 2012 at 16:54 UTC
    To expand upon the AnonMonk's suggestion.
    Maybe this helps to show what is going on?
    #!/usr/bin/perl -w use strict; my $string = "Twinkle twinkle little star"; my @matches = $string =~ m/twinkle/ig; print "Matches are: @matches\n"; # Matches are: Twinkle twinkle print "Number of matches: ",scalar @matches,"\n"; print "\n"; # this is the same without creating @matches # the () is a list and $n here is number of things # in that list # # Without the intervening ()=, to force list context, # you just get the "truthfulness" (0,1) of the match # with this, you get the number of things in the list # without having to create a named array (@matches) my $n = () = $string =~ m/twinkle/ig; print "Number of occurences = $n\n"; __END__ Matches are: Twinkle twinkle Number of matches: 2 Number of occurences = 2
    PS: I try to avoid assigning to $_ when possible (and sometimes this is necessary), but I figure that $_ "belongs to Perl". The expression:
    foreach ($string) { s/^\s*//; #delete leading spaces s/\s*$//; #delete trailing spaces }
    is seen often and has this effect of assigning $string to $_. $string gets modified due to "aliasing".
Re: Error in my Regular expression pattern
by mendeepak (Scribe) on Mar 19, 2012 at 11:54 UTC

    Check this code

    $_ = "Twinkle twinkle little star"; $n = m/twinkle/i; print "Number of occurences = $n\n"; while(/twinkle/ig) { $count++; } print "Found $count times\n";
    i am still searching why your code is not working!!! q

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://960264]
Approved by GrandFather
zentara...oO 1 more reason I prefer Perl to Python is I can't believe how long Python takes to compile, and you can't disable the myriad of tests
[LanX]: so that's where you've been the last two years? Compiling Python?
[zentara]: LanX no! I was learning why Krishna made me into a unicorn. :-)
[LanX]: The old chromosone question ... Why Y???

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (8)
As of 2017-03-30 16:49 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (361 votes). Check out past polls.