As my disclaimer warned, there may be a better solution. And it does use a single preg_replace.
Consider the result of the following code.
$strings = array(
'word word word this word word',
'word word word {code}this{/code} word word',
'word this word this word word',
'word this word {code}this{/code} word word',
'word {code}this{/code} word this word word',
'word {code}this{/code} word {code}this{/code} word word',
'word word word {code}this{/code} word this word',
'word this word {code}this{/code} word this word',
'word {code}this{/code} word this word this word',
'word {code}this{/code} word {code}this{/code} word this word',
'word word word {code}word this word{/code} word word',
'word this word this word word',
'word this word {code}word this word{/code} word word',
'word {code}word this word{/code} word this word word',
'word {code}word this word{/code} word {code}word this word{/code} word word',
'word word word {code}word this word{/code} word this word',
'word this word {code}word this word{/code} word this word',
'word {code}word this word{/code} word this word this word',
'word {code}word this word{/code} word {code}word this word{/code} word this word',
);
foreach($strings as $string)
echo preg_replace(
'/(this)(?=((?!\{\/code\}).)*(\{code\}|$))/s',
'that',
$string)."<br>";
(Note that for the sake of rendering, [ and ] have been replaced by { and }).
Replace "this" and "that" with the smiley and its replacement. If you're going to use arrays of smileys, then the entire regexp will need to be stored in each element of the array, not just the smiley itself.