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

What would be the fastest way to count the number of matches in a string without altering the string? Is something minorly complicated necessary, as m// doesn't count the matches? (Or am I just completely wrong...) thanks!

Replies are listed 'Best First'.
Re: number of matches
by BrowserUk (Patriarch) on Sep 02, 2004 at 21:55 UTC
    my $s = 'the quick brown fox jumps over the lazy dog'; my $vowels = () = $s =~ m[[aeiou]]g; print "There are $vowels vowels in '$s'"; There are 11 vowels in 'the quick brown fox jumps over the lazy dog'

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: number of matches
by wufnik (Friar) on Sep 02, 2004 at 21:53 UTC
    i am presuming you do not want *overlapping* matches;

    ie you want simple repeat detection: if this is the case something like:
    my $searchstring = 'humptydumpty'; my @matches = $searchstring =~ /umpty/g;
    should work, leaving you able to access the number of matches by using scalar @matches or whatever
    ...wufnik

    -- in the world of the mules there are no rules --
Re: number of matches
by bobf (Monsignor) on Sep 02, 2004 at 22:01 UTC

    If you are counting characters, you can use tr//. If you are matching strings, you can use s//. Both return the number of substitutions made:

    $count = ($line =~ tr/X/X/); $count = ($line =~ s/(match1|match2)/$1/g);

    Just make sure you reset the position with the pos function if you are using a string (vs a single character) and you want to find overlapping matches.

    HTH
      Didn't benchmark - but I believe tr/X/X/ is still modifying the string on the backend (unless there is some unknown optimization).

      It is better to leave off the second X as in tr/X//. This will not attempt to modify the string and will still return the count - as in:
      perl -e '$a="aaa"; $i=$a=~tr/a//; print "($i)($a)\n";'


      my @a=qw(random brilliant braindead); print $a[rand(@a)];
Re: number of matches
by Anonymous Monk on Sep 03, 2004 at 09:16 UTC
    $count = () = $str =~ /PATTERN/g; # Non-overlapping mat +ches $count = () = $str =~ /(?=(PATTERN))/g; # Overlapping matches $count = 0; $str =~ /PATTERN(?{$count ++})(?!)/; # All matches
Re: number of matches
by frank_2k4 (Acolyte) on Sep 02, 2004 at 21:57 UTC
    You could use a counter
    counter = 0; @regex = qw( reg ex patterns ); for (@regex){ if (/\Q$_\E/){ $counter ++' } } print $counter;
Re: number of matches
by Anonymous Monk on Sep 03, 2004 at 18:58 UTC
    $count=scalar(my @dummy = $string=~m/$regex/g);
    will count the matches. If you don't assign the pattern match to an array, m//g will interpret this as a scalar context and only return the first occurrence, and the scalar function will then return 1.