替换双换行符,除非标签

Replace double line breaks except when tags

我有一些数据库内容作为变量,我想将双换行符变成 <p>...</p>

对于单个换行符,我想添加 <br />

我可以使用:

$content = nl2br($content, false);
$content = '<p>' . preg_replace('#(<br>[\r\n\s]+){2}#', '</p><p>', $content) . '</p>';

但是,我需要排除具有 h2、h3、h4、ul 且位于 ul 标签内的段落。但我仍然需要在其他 HTML 标签周围添加 p 标签,例如 <strong> <blockquote> <img> <i> <em><caption>

示例文本为:

<h2>Lorem ipsum dolor sit amet, consectetur adipiscing elit</h2>

Vivamus vel tempor turpis, <strong>non rutrum quam</strong>. Suspendisse ac rhoncus felis, eget porta lectus. 

Nam vulputate sapien risus, vel vehicula mi volutpat sed. 

<ul>
<li>Sed feugiat nibh at nisl eleifend scelerisque.</li>
<li>Aliquam non maximus ipsum. Aliquam erat volutpat.</li>
</ul>

<h3>Praesent eget diam sit amet leo vehicula sagittis at quis tortor</h3>

Nunc nec sem ac nunc tincidunt aliquam ut nec dolor. Nulla facilisi.

<img alt="xxxx" src="xxx.png" class="xxxxx"/> 

<caption><i>ccccc</i></caption> 

<img alt="xxxx" src="xxx.png" class="xxxxx"/> 

<i>ccccc</i>

<strong>Nunc nec sem ac nunc tincidunt aliquam ut nec dolor. Nulla facilisi.</strong>

Vivamus vel tempor turpis, <strong>non rutrum quam</strong>. Suspendisse ac rhoncus felis, eget porta lectus.

Nunc nec
Nunc nec
Nunc nec

<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Vivamus vel tempor turpis <a href=""></a></p>&mdash; xxxxx (@xxxxxx) <a href="https://twitter.com/xxxx/status/x?ref_src=x">February 15, 2019</a></blockquote>

<script async src="" charset="utf-8"></script>

您应该将 <br> 添加到如下列表中:

$content = '<p>' . preg_replace('#([\<br\>\r\n\s]{2})#', '</p><p>', $content) . '</p>';

我建议不要使用 nl2br() 函数——您将在不需要的地方到处注入 <br> 标签。

相反,我建议您直接在换行符之外执行正则表达式,忽略已经被标签包围的行,如下所示:

(?i)^(?!((<\/|<)(h[1-6]|ul|li|script|blockquote)(\s.+)*>))(.+)(?!(<(\/)>))$

如果要排除更多标签,请将它们放在 (h[1-6]|ul|li|script|blockquote) 组中。

我们来分解一下:

  • (?i) 使所有后续匹配不区分大小写
  • ^ 断言行首的位置
  • ?!() 分组是负向前瞻
  • (<\/|<) 表示我们匹配开始或结束标签
  • h[1-6] 匹配 h1、h2、h3 等
  • (\s.+)*> 匹配开始标签内的多余垃圾,例如 <script xyz>
  • (.+) 就是我们想要包裹段落标签的地方
  • <(\/)>中的</code>匹配我们匹配的原始标签,为结束标签</li> </ul> <p>请注意,上面正则表达式中的 <code>(.+) 是第 5 组,这就是您想要 包围 <p> 标签的内容。您可以使用 preg_replace() 中的 </code> 标签引用第一个组,这样您就可以在该组周围包含开始和结束 <code><p> 标签。

    这是一个实际的例子: https://regex101.com/r/TQGbaq/2

    因此您的代码可能如下所示:

    $regex = '#(?i)^(?!((<\/|<)(h[1-6]|ul|li|script|blockquote)(\s.+)*>))(.+)(?!(<(\/)>))$#';
    $content = preg_replace($regex, "<p></p>", $content);