You can use this (to illustrate Jack's idea):
$pattern = <<<'LOD'
~
(['"`])
(?> [^`"'\\]++ | \\{2} | \\. | (?!\1)["'`] )*
\1
~xs
LOD;
$result = preg_replace_callback($pattern, function($m) {
return '<span class="sE">'
. str_replace(array('"', "'"), array('"', '''), $m[0])
. '</span>';
}, $r);
An other way is to perform the quotes replacement first and to split after:
$pattern = <<<'LOD'
~
(&(?>quot|039);|`)
(?> [^&`\\]++ | \\{2} | \\. | (?!\1)[&`] )*
\1
~xs
LOD;
$result = preg_replace($pattern,
'<span class="sE">$0</span>',
str_replace(array('"', "'"), array('"', '''), $r));
You can use htmlentities
instead of str_replace
in the two examples.