You can use this:
$pattern = '~(\[' . $tag . '])((?>[^[]++|\[(?!/?+' . $tag . '])|(?R))*+)(\[/'
. $tag . '])~i';
$message = preg_replace_callback($pattern,
function ($m) {
return $m[1]
. str_ireplace('[smg', '[smg', $m[2])
. $m[3];
}, $message);
Notice: an other way (more readable) to write the same pattern with verbose mode and heredoc syntax:
$pattern = <<<EOF
~
(\[ $tag ])
( (?> [^[]++ | \[(?!/?+ $tag ]) | (?R) )*+ )
(\[/ $tag ])
~ix
EOF;