Take the 2-minute tour ×

What is the fastest way to count the number of times a certain string appears in a bigger one? My best guess would be to replace all instances of that string with nothing, calculate the difference of lengths and divide by the length of the substring, but that seems rather slow, and I need to analyze big amounts of data.

share|improve this question
Might want to check this out... although it's from 1999, and there are most likely other ways to do this sort of thing efficiently: perlmonks.org/… –  summea Mar 2 '12 at 18:35
perldoc -q count –  toolic Mar 2 '12 at 18:36
Can these overlap? –  tchrist Mar 2 '12 at 18:53

4 Answers 4

up vote 28 down vote accepted

You can capture the strings, then count them. It can be done by applying a list context to the capture with ():

my $x = "foo";
my $y = "foo foo foo bar";
my $c = () = $y =~ /$x/g;  # $c is now 3

You can also capture to an array and count the array. Same principle, different technique:

my @c = $y =~ /$x/g;
my $count = @c;
share|improve this answer
Thanks! It's a lot like the second solution. –  ronash Mar 2 '12 at 18:42
@ronash It's the same solution. One uses a temp variable, the other does not. You could also do my $count = @c = $y =~ /$x/g, but instead you can simply ignore @c and use (). Which is the best, if you do not care about the actual matches. –  TLP Mar 2 '12 at 18:46
This doesn't work if $x contains certain regex characters, since $x is interpreted as a regex. Add \Q to fix this, eg. /\Q$x/g. See quotemeta for more information. –  tuomassalo Mar 12 '13 at 12:14
my $string = "aaaabbabbba";
my @count = ($string =~ /a/g);
print @count . "\n";


my $count = ($string =~ s/a/a/g);
share|improve this answer
Thanks! Will that work if more than one letter is sought? –  ronash Mar 2 '12 at 18:42
Erm, yes ... it's a regular expression, you can match on anything. –  Brian Roach Mar 2 '12 at 18:45

You could use a global regex. Something like:

my @matches = $bigstring =~ /($littlestring)/g;
my $count = @matches;
share|improve this answer
That seems like the simplest solution, so I think I'll use it, unless there's a faster one? Thanks! –  ronash Mar 2 '12 at 18:41
I'm not sure about the speed of regex, but I'm sure that just using matching operations is quicker than substitutions. And I can't think of a solution that doesn't have something to do with regex (it'll be very interesting to see otherwise!) –  Mattrition Mar 2 '12 at 18:46

Just for completeness you can repeatedly call the index function in a loop and count all the times it returned the index of the substring in the string, and change the starting position. That would avoid using regexes, and in my testing is a bit faster than the regex solutions.

I've adapted a sub to do that from here: http://www.misc-perl-info.com/perl-index.html

sub occurrences {

    my( $x, $y ) = @_;

    my $pos = 0;
    my $matches = 0;

    while (1) {
        last if($pos < 0);

    return $matches;
share|improve this answer

Your Answer


