I have a string. With "pre" tag inside. I don't want to replace the texts in this pre tag. How can I do that?
<?php
$str="
<b>test</b>
<pre>
<b>test</b>
</pre>
<b>test</b>
";
function htmltobb($str){
$str=preg_replace('(<b>)','[b]',$str);
$str=preg_replace('(</b>)','[/b]',$str);
return $str;
}
echo htmltobb($str);
?>
result:
[b]test[/b]
<pre>
[b]test[/b]
</pre>
[b]test[/b]
what i want?
[b]test[/b]
<pre>
<b>test</b> <-- this line not replaced
</pre>
[b]test[/b]
thank you for all answers
CodePudding user response:
A messy approach could be taking everything between pre
tags, HTML encoding it, parse everything else, then decode the entities back to characters... this assumes regexs are required and you already have read about their pitfalls.
$str="
<b>test</b>
<pre>
<b>test</b>
</pre>
<b>test</b>
";
echo preg_replace_callback(htmlspecialchars('~(?s)<pre>.*?</pre>~'), function($match) { return htmlspecialchars_decode($match[0]);}, preg_replace('~<(/?)b>~','[$1b]', preg_replace_callback('~(?s)<pre>.*?</pre>~', function($match) { return htmlspecialchars($match[0]);}, $str)));
Start with:
<b>test</b>
<pre>
<b>test</b>
</pre>
<b>test</b>
First run converts to:
<b>test</b>
<pre>
<b>test</b>
</pre>
<b>test</b>
Second converts to:
[b]test[/b]
<pre>
<b>test</b>
</pre>
[b]test[/b]
Third puts it back as intended:
[b]test[/b]
<pre>
<b>test</b>
</pre>
[b]test[/b]
CodePudding user response:
You need to go cutting your string, do the replace when not inside a pre, and not when yes inside a pre.
$str="
<b>test</b>
<pre>
<b>test</b>
</pre>
<b>test</b>
";
echo htmltobb($str);
function htmltobb($str){
$aux = '';
$posB = 0;
while (($posA = mb_strpos($str, '<pre>', $posB)) !== false) {
$aux .= preg_replace(['(<b>)', '(</b>)'], ['[b]', '[/b]'], mb_substr($str, 0, $posA));
$posB = mb_strpos($str, '</pre>', $posA);
$aux .= mb_substr($str, $posA, $posB - $posA);
}
$aux .= preg_replace(['(<b>)', '(</b>)'], ['[b]', '[/b]'], mb_substr($str, $posB));
return $aux;
}