I have this web page where users can add smilies to their comments. And I want to limit the number of smilies per comment. The “system” works but I have some problems with the regex part.
I have my smilies defined in a config file like so:
$config['Smilies'] = Array (
// irrelevant stuff
'smilies' => Array (
':)' => 'smile.gif',
':(' => 'sad.gif',
// some more smilies
's:10' => 'worship.gif',
's:11' => 'zip.gif',
's:12' => 'heart.gif',
// some more smilies
's:1' => 'dry.gif',
's:2' => 'lol.gif',
's:3' => 'lollol.gif',
// some more smilies
)
);
And then when I validate the comment (to see how many smilies are there), I loop trough this array and match the smile to the content of the comment. The regex is used like this:
foreach ( $this->config['smilies'] as $smilie => $smilieImage )
{
$matches = Array ();
Preg_Match_All ( '/' . Preg_Quote ( $smilie ) . '/i', $Content, $matches );
$numOfFoundSmilies += Count ( $matches[0] );
}
The problem is that the if I enter “s:10” into the comment, the above code will find two matches: “s:10” and “s:1”. My knowledge of regular expressions is very poor, and I can’t figure this one out.
Regular expressions are greedy by default (at least PCREs). Usually you could circumvent this:
In your case, this doesn’t help much, since you can’t just throw in a question mark somewhere. The only possibility is to re-order your search array and instantly replace the found places. Search first for
s:10and second fors:1, and use preg_replace() instead of the matching. This way, the second doesn’t find the first anymore.Another possibility: Split your search array in two. If you know, that the one always has the structure ‘s:’ plus digits, you could have your regexp in this second loop like
with
(?![0-9])a look ahead expression looking for any non-digit.And a third one: If you allow (== convert) smileys only at certain places, you could use this:
\bis a “word boundary”, usually any not-(letter, digit, underscore). Drawback is obviously, that not all smileys (like “abc;-)xyz”) will be found.