在两个标记之间搜索并替换,使用 PHP 正则表达式。

huangapple go评论66阅读模式
英文:

search and replace but only if between two markers php regex

问题

I want to replace the <br> tags with a space in a string containing html, but only if the tag is within a <div class="nobr"> ..... </div> sequence. I presume the best way is to use preg_replace but I'm having difficulty finding the regex expression to use for the pattern... (there will be multiple line break tags and more than one "nobr" div)

e.g Simple example - From this:

keep this<br>line break<div class="nobr"> but replace this linebreak<br>with a space</div>

To become:

keep this<br>line break<div class="nobr"> but replace this linebreak with a space</div>

英文:

I want to replace the <br> tags with a space in a string containing html, but only if the tag is within a <div class="nobr"> ..... </div> sequence. I presume the best way is to use preg_replace but I'm having difficulty finding the regex expression to use for the pattern... (there will be multiple line break tags and more than one "nobr" div)

e.g Simple example - From this:

keep this<br>line break<div class="nobr"> but replace this linebreak<br>with a space</div>

To become:

keep this<br>line break<div class="nobr"> but replace this linebreak with a space</div>

答案1

得分: 1

你可以首先匹配 nobr 元素,然后使用 preg_replace_callback 和回调函数来替换 <br>

$pattern = '/<div class="nobr">(.*?)<\/div>/s';
// 此正则表达式模式将匹配以 "<div class="nobr">" 开头,并以 "</div>" 结尾的字符串,并捕获其中的所有字符,包括换行符(使用 "s" 标志)。

$string = preg_replace_callback($pattern, function ($matches) {
  return str_replace('<br>', ' ', $matches[0]);
  // preg_replace_callback 函数将在每个匹配的 "nobr" div 中用空格替换所有 "<br>" 标签。
}, $string);

这仅在没有嵌套的 div 时有效,因为关闭标签会匹配嵌套的 div 关闭标签。如果有嵌套的 div,你需要使用 DOM 解析器

$doc = new DOMDocument();
$doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$xpath = new DOMXPath($doc);
$nobr_divs = $xpath->query("//div[contains(concat(' ', normalize-space(@class), ' '), ' nobr ')]");

foreach ($nobr_divs as $nobr_div) {
    $br_tags = $nobr_div->getElementsByTagName('br');
    foreach ($br_tags as $br_tag) {
        $text = $doc->createTextNode(' ');
        $nobr_div->replaceChild($text, $br_tag);
    }
}

$new_html = $doc->saveHTML();
echo $new_html;
英文:

You could first match the nobr elements and use a callback function with preg_replace_callback to replace the <br>.

$pattern = '/<div class="nobr">(.*?)<\/div>/s';
// This regex pattern will match any string that starts with 
// "<div class="nobr">" and ends with "</div>", and capture 
// all characters in between, including line breaks (using the "s" flag).

$string = preg_replace_callback($pattern, function ($matches) {
  return str_replace('<br>', ' ', $matches[0]);
  // The preg_replace_callback function will replace all 
  // "<br>" tags with spaces within each matched "nobr" div.
}, $string);

This would only work if you don't have nested divs, since the closing tag would match the nested div closing tag. If that's the case you need to use a DOM parser:

$doc = new DOMDocument();
$doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$xpath = new DOMXPath($doc);
$nobr_divs = $xpath->query("//div[contains(concat(' ', normalize-space(@class), ' '), ' nobr ')]");

foreach ($nobr_divs as $nobr_div) {
    $br_tags = $nobr_div->getElementsByTagName('br');
    foreach ($br_tags as $br_tag) {
        $text = $doc->createTextNode(' ');
        $nobr_div->replaceChild($text, $br_tag);
    }
}

$new_html = $doc->saveHTML();
echo $new_html;

huangapple
  • 本文由 发表于 2023年4月17日 04:06:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76032416.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定