title: How exactly do Regular Expression word boundaries work in PHP?
body: <p>I'm currently writing a library for matching specific words in content.</p>
  
  <p>Essentially the way it works is by compiling words into regular expressions, and running content through said regular expressions.</p>
  
  <p>A feature I want to add is specifying whether a given word to match must start and/or end a word. For example, I have the word <code>cat</code>. I specify that it <strong>must start a word</strong>, so <code>catering</code> will <strong>match</strong> as <code>cat</code> is at the start, but <code>ducat</code> <strong>won't match</strong> as <code>cat</code> doesn't start the word.</p>
  
  <p>I wanted to do this using <a href="http://www.regular-expressions.info/wordboundaries.html" rel="nofollow noreferrer">word boundaries</a>, but during some testing I found it doesn't work as I'd expect it to.</p>
  
  <p>Take the following,</p>
  
  <pre><code>preg_match("/(^|\b)@nimal/i", "something@nimal", $match);
  preg_match("/(^|\b)@nimal/i", "something!@nimal", $match);
  </code></pre>
  
  <p>In the statements above I would expect the following results,</p>
  
  <pre><code>&gt; false
  &gt; 1 (@nimal)
  </code></pre>
  
  <p>But the result is instead the opposite,</p>
  
  <pre><code>&gt; 1 (@nimal)
  &gt; false
  </code></pre>
  
  <p>In the first, I would expect it to fail as the group will eat the <code>@</code>, leaving <code>nimal</code> to match against <code>@nimal</code>, which obviously it doesn't. Instead, the group matchs an empty string, so <code>@nimal</code> is matched, meaning <code>@</code> is considered to be part of the word.</p>
  
  <p>In the second, I would expect the group to eat the <code>!</code> leaving <code>@nimal</code> to match the rest (which it should). Instead, it appears to combine the <code>!</code> and <code>@</code> together to form a word, which is confirmed by the following matching,</p>
  
  <pre><code>preg_match("/g\b!@\bn/i", "something!@nimal", $match);
  </code></pre>
  
  <p>Any ideas why regular expression does this?</p>
  
  <p>I'd just <em>love</em> a page that clearly documents how word boundaries are determined, I just can't find one for the life of me.</p>