 <p>Regular expressions are like the <code>sort</code> function in Perl. You think it's pretty simple because it's just a single command, but in the end, it uses a lot of processing power to do the job.</p> <p>There are certain things you can do to help out:</p> <ol> <li>Keep your syntax simple as possible.</li> <li>Precompile your regular expression pattern by using qr// if you're using that regular expression in a loop. That'll prevent Perl from having to <em>compile</em> your regular expression with each loop.</li> <li>Try to avoid regular expression syntax that has to do <a href="http://perldoc.perl.org/perlre.html#Special-Backtracking-Control-Verbs" rel="nofollow">backtracking</a>. This usually ends up being the most general matching patterns (such as <code>.*</code>). </li> </ol> <p>The wretched truth is that after decades of writing in Perl, I've never masted the deep dark secrets of regular expression parsing. I've tried many times to understand it, but that usually means doing research on the Web, and ...well... I get distracted by all of the other stuff on the Web.</p> <p>And, it's not that difficult, any half decent developer with an IQ of 240, and a penchant for sadism should easily be able to pick it up. </p> <hr> <blockquote> <p>@David W.: I guess I'm confused on backtracking. I had to read your link several times but still don't quite understand how to implement it (or, not implement it) in my case. – user522962</p> </blockquote> <p>Let's take a simple example:</p> <pre><code>my $string = 'foobarfubar'; $string =~ /foo.*bar.*(.+)/; my $result = $1; </code></pre> <p>What will <code>$result</code> be? It will be <code>r</code>. You see how that works? Let's see what happens.</p> <p>Originally, the regular expression is broken into tokens, and the first token <code>foo.*</code> is used. That actually matches the whole string:</p> <pre><code>"foobarfubar" =~ /foo.*/ </code></pre> <p>However, if the first regular expression token captures the whole string, the rest of the regular expression fails. Therefore, the regular expression matching algorithm has to back track:</p> <pre><code>"foobarfubar" =~ /foo.*/ #/bar.*/ doesn't match "foobarfuba" =~ /foo.*/ #/bar.*/ doesn't match. "foobarfub" =~ /foo.*/ #/bar.*/ doesn't match. "foobarfu" =~ /foo.*/ #/bar.*/ doesn't match. "foobarf" =~ /foo.*/ #/bar.*/ doesn't match. "foobar" =~ /foo.*/ #/bar.*/ doesn't match. ... "foo" =~ /foo.*/ #Now /bar.*/ can match! </code></pre> <p>Now, the same happens for the rest of the string:</p> <pre><code>"foobarfubar" =~ /foo.*bar.*/ #But the final /.+/ doesn't match "foobarfuba" =~ /foo.*bar.*/ #And the final /.+/ can match the "r"! </code></pre> <p>Backtracking tends to happen with the <code>.*</code> and <code>.+</code> expression since they're so loose. I see you're using non-greedy matches which can help, but it can still be an issue if you are not careful -- especially if you have very long and complex regular expressions.</p> <p>I hope this helps explain backtracking.</p> <p>The issue you're running into isn't that your program doesn't work, but that it takes a long, long time.</p> <p>I was hoping that the general gist of my answer is that regular expression parsing isn't as simple as Perl makes it out to be. I can see the command <code>sort @foo;</code> in a program, but forget that if <code>@foo</code> contains a million or so entries, it might take a while. In theory, Perl could be using a bubble sort and thus the algorithm is a O<sup>2</sup>. I hope that Perl is actually using a more efficient algorithm and my actual time will be closer to O * log (O). However, all this is hidden by my simple one line statement.</p> <p>I don't know if backtracking is an issue in your case, but you're treating an entire webpage output as a single string to match against a regular expression which could result in a very long string. You attempt to match it against another regular expression which you do over and over again. Apparently, that is quite a process intensive step which is hidden by the fact it's a single Perl statement (much like <code>sort @foo</code> hides its complexity).</p> <p>Thinking about this on and off over the weekend, you really should not attempt to parse HTML or XML with regular expressions because it is so sloppy. You end up with something rather inefficient and fragile.</p> <p>In cases like this may be better off using something like <a href="http://search.cpan.org/~gaas/HTML-Parser-3.68/Parser.pm" rel="nofollow">HTML::Parser</a> or <a href="http://search.cpan.org/~grantm/XML-Simple-2.18/lib/XML/Simple.pm" rel="nofollow">XML::Simple</a> which I'm more familiar with, but doesn't necessarily work with poorly formatted HTML.</p> <p>Perl regular expressions are nice, but they can easily get out of our control.</p>