title: Sliding window pattern match in perl or matlab regular expressions
body: <p>I am trying to use either Perl or MATLAB to parse a few numbers out of a single line of text.  My text line is:</p>
  
  <p>t10_t20_t30_t40_</p>
  
  <p>now in matlab, i used the following script </p>
  
  <pre><code>str = 't10_t20_t30_t40_';
  a = regexp(str,'t(\d+)_t(\d+)','match')
  </code></pre>
  
  <p>and it returns</p>
  
  <pre><code>a = 
  
  't10_t20'    't30_t40'
  </code></pre>
  
  <p>What I want is for it to also return 't20_t30', since this obviously is a match.  Why doesn't regexp scan it?  </p>
  
  <p>I thus turned to Perl, and wrote the following in Perl:</p>
  
  <pre><code>#!/usr/bin/perl -w
  $str = "t10_t20_t30_t40_";
  while($str =~ /(t\d+_t\d+)/g)
  {
      print "$1\n";
  }
  </code></pre>
  
  <p>and the result is the same as matlab</p>
  
  <pre><code>t10_t20
  t30_t40
  </code></pre>
  
  <p>but I really wanted "t20_t30" also be in the results.  </p>
  
  <p>Can anyone tell me how to accomplish that?  Thanks!</p>
  
  <p>[update with a solution]:
  With help from colleagues, I identified a solution using the so-called "look-around assertion" afforded by Perl.  </p>
  
  <pre><code>#!/usr/bin/perl -w
  $str = "t10_t20_t30_t40_";
  while($str =~ m/(?=(t\d+_t\d+))/g)
  {print "$1\n";}
  </code></pre>
  
  <p>The key is to use "zero width look-ahead assertion" in Perl.  When Perl (and other similar packages) uses regexp to scan a string, it does not re-scan what was already scanned in the last match.  So in the above example, t20_t30 will never show up in the results.  To capture that, we need to use a zero-width lookahead search to scan the string, producing matches that do not exclude any substrings from subsequent searches (see the working code above).  The search will start from zero-th position and increment by one as many times as possible if "global" modifier is appended to the search (i.e. m//g), making it a "greedy" search.  </p>
  
  <p>This is explained in more detail in <a href="http://linuxshellaccount.blogspot.com/2008/09/finding-overlapping-matches-using-perls.html" rel="nofollow">this blog post</a>.</p>
  
  <p>The expression (?=t\d+_t\d+) matches any 0-width string followed by t\d+_t\d+, and this creates the actual "sliding window".  This effectively returns ALL t\d+_t\d+ patterns in $str without any exclusion since every position in $str is a 0-width string.  The additional parenthesis captures the pattern while its doing sliding matching (?=(t\d+_t\d+)) and thus returns the desired sliding window outcome.  </p>