【问题标题】:How do I use preg_replace to insert text string between 3rd and 4th paragraph?如何使用 preg_replace 在第 3 和第 4 段之间插入文本字符串?
【发布时间】:2015-06-09 21:07:57
【问题描述】:

我正在尝试弄清楚如何在 Wordpress 帖子中创建一个称为“pullquote”的通用报纸设备。 (但这不是严格意义上的 Wordpress 问题;它更像是一个通用的正则表达式问题。)我有一个标签来围绕帖子中的文本。我想复制标签之间的文本(我知道该怎么做)并将其插入到帖子中 p 标签的第 3 和第 4 个实例之间。

下面的函数查找文本并去除标签,但只是将匹配的文本添加到开头。我需要帮助定位第 3/4 段

或者...也许我想错了。也许有一些方法可以像使用 jQuery nth-child 一样定位元素?

帖子:

<p>If you wanna improve yer German, don't try to read Heine or some elevated crap... watch old episodes of [callout]Tatort or Bukow & Konig[/callout].</p>
<p>If I were teaching a music appreciation I wouldn't teach Beethoven. I'd teach Stamitz and average composers.</p>
<p>And here is a 3rd paragraph.</p>
<p>And here is a 4th paragraph.</p>

想要的结果

<p>If you wanna improve yer German, don't try to read Heine or some elevated crap... watch old episodes of Tatort or Bukow & Konig.</p>
<p>If I were teaching a music appreciation I wouldn't teach Beethoven. I'd teach Stamitz and average composers.</p>
<p>And here is a 3rd paragraph.</p>
<blockquote class="pullquote">Tatort or Bukow & Konig</blockquote>
<p>And here is a 4th paragraph.</p>

到目前为止,这就是我所拥有的代码:

function jchwebdev_pullquote( $content ) {
    $newcontent = $content;
    $replacement = '$1';
    $matches = array();
    $pattern = "~\[callout\](.*?)\[/callout\]~s";
    // strip out 'shortcode'
    $newcontent = preg_replace($pattern, $replacement, $content);
    if( preg_match($pattern, $content, $matches)) {
      // now have formatted pullquote 
      $pullquote = '<blockquote class="pullquote">' .$matches[1] . '</blockquote>';
      // now how do I target and insert $pullquote
      // between 3rd and 4th paragraph?
      preg_replace($3rd_4th_pattern, $3rd_4th_replacement,
      $newcontent);
      return $newcontent;
    }
    return $content;    
}
add_filter( 'the_content' , 'jchwebdev_pullquote');

编辑:我想修改我的问题,使其更具体一些 Wordpress。 Wordpress 实际上将换行符转换为

个字符。大多数 Wordpress 帖子甚至不使用显式的“p”标签,因为它们是不需要的。到目前为止,解决方案的问题在于它们似乎去掉了换行符,所以如果帖子(源文本)有换行符,它看起来很奇怪。

典型的真实世界 Wordpress 帖子:

If you wanna improve yer German, don't try to read Heine or some elevated crap... watch old episodes of [callout]Tatort or Bukow & Konig[/callout].

If I were teaching a music appreciation I wouldn't teach Beethoven. I'd teach Stamitz and average composers.

And here is a 3rd paragraph.


And here is a 5th paragraph.

Wordpress 是这样渲染的:

<p>If you wanna improve yer German, don't try to read Heine or some elevated crap... watch old episodes of [callout]Tatort or Bukow & Konig[/callout].</p>
<p>If I were teaching a music appreciation I wouldn't teach Beethoven. I'd teach Stamitz and average composers.</p>
<p>And here is a 3rd paragraph.</p>
<p></p>
<p>And here is a 5th paragraph.</p>

所以在一个完美的世界里,我想拿那个“典型的现实世界帖子”并让 preg_replace 将它渲染为:

If you wanna improve yer German, don't try to read Heine or some elevated crap... watch old episodes of Tatort or Bukow & Konig.

If I were teaching a music appreciation I wouldn't teach Beethoven. I'd teach Stamitz and average composers.

And here is a 3rd paragraph.

<blockquote class="callout">Tatort or Bukow & Konig</blockquote>

And here is a 5th paragraph.

...然后 Wordpress 将呈现为:

<p>If you wanna improve yer German, don't try to read Heine or some elevated crap... watch old episodes of Tatort or Bukow & Konig.</p>
<p>If I were teaching a music appreciation I wouldn't teach Beethoven. I'd teach Stamitz and average composers.</p>
<p>And here is a 3rd paragraph.</p>
<blockquote class="callout">Tatort or Bukow & Konig</blockquote>
<p>And here is a 5th paragraph.</p>

也许这离题太远了,我应该在 Wordpress 论坛上重新发布,但我认为我需要的只是一种方法来改变 preg_replace 以使用换行符而不是

并弄清楚如何从返回的字符串中去除那些换行符。

感谢到目前为止的所有帮助!

【问题讨论】:

  • 请用输入和所需输出更新您的问题。

标签: regex wordpress preg-replace


【解决方案1】:

您可以在单个 preg_replace 函数中执行此操作。

$re = "~^(?:(?!/p).)*<p>(?:(?!/p).)*\\[callout\\](.*?)\\[/callout\\].*?</p>(?:[^<>]*<p>.*?</p>){2}[^<]*\\K~s";
$str = "<p>If you wanna improve yer German, don't try to read Heine or some elevated crap... watch old episodes of [callout]Tatort or Bukow & Konig[/callout].</p>\n<p>If I were teaching a music appreciation I wouldn't teach Beethoven. I'd teach Stamitz and average composers.</p>\n<p>And here is a 3rd paragraph.</p>\n<p>And here is a 4th paragraph.</p>";
$subst = "<blockquote class=\"pullquote\">$1</blockquote>\n";
$result = preg_replace($re, $subst, $str);
echo $result;

DEMO

Code in eval

【讨论】:

  • 我试图在 regex101 上运行它,但无法匹配。我错过了什么?
  • 这在 Wordpress 中无法正常工作...但我认为这只是因为 Wordpress 不是很纯的 html(创建自己的

    标签等)不过谢谢。

【解决方案2】:

只需使用(.*?&lt;/p&gt;){3}\Ks 修饰符,就可以实现你想要的:

preg_replace("@(.*?</p>){3}\K@s", $pullquote, $content);

我对您的功能进行了一些更改以使其正常工作:

function jchwebdev_pullquote( $content )
{
    $pattern = "~\[callout\](.*?)\[/callout\]~s";
    if(preg_match($pattern, $content, $matches))
    {
      $content = preg_replace($pattern, '$1', $content);
      $pullquote = '<blockquote class="pullquote">' .$matches[1] . '</blockquote>';
      $content = preg_replace("@(.*?</p>){3}\K@s", $pullquote, $content);
      return $content;
    }
    return $content;    
}

Regex live demo

PHP live demo

更新 #1

优化:使用单个preg_replace 以避免应用多个模式:

function jchwebdev_pullquote( $content )
{
    $pattern = "\[callout\](.*?)\[/callout\]";
    if(preg_match("@(?s)$pattern@", $content, $matches))
    {
      $content = preg_replace("@(?s)($pattern)((.*?</p>){3})@", '\2\3<blockquote class="pullquote">\2</blockquote>', $content);
      return $content;
    }
    return $content;
}

PHP live demo

【讨论】:

  • @jchwebdev 糟糕,使用捕获组是个错误。现在再检查一遍。
  • 更新#1 似乎有效。仍然存在一个问题,但我认为这更多地与 Wordpress 如何创建自己的段落有关。是否可以将 preg_replace 模式从

    更改为简单的换行符?

  • @jchwebdev 为什么要将&lt;p&gt; 更改为换行符?新行并不意味着新段落。
  • Wordpress(以及 Drupal、Joomla 等其他 CMS)自动将换行符呈现为

    。 IOW:您很少会在 Wordpress 帖子中输入

    标签,因为它是多余的。

  • 为了清楚起见,您的解决方案(至少在 Wordpress 中)的问题在于它去除了换行符。请参阅我上面的编辑。这可能是我不理解 Wordpress 渲染的错。
【解决方案3】:

如果要使用PHP HTML/XML解析,请参考How do you parse and process HTML/XML in PHP?

对于正则表达式解决方案,这里是一个正则表达式解决方案:

查找: (?s)((?:&lt;p&gt;.*?&lt;\/p&gt;\s*){3})

这个正则表达式只会捕获前 3 个 &lt;p&gt; 标签,然后在它们之后添加一个节点。

替换: $1&lt;blockquote class="pullquote"&gt;Tatort or Bukow &amp; Konig&lt;/blockquote&gt;\n

代码:

$re = "/(?s)((?:<p>.*?<\\/p>\\s*){3})/"; 
$str = "<p>If you wanna improve yer German, don't try to read Heine or some elevated crap... watch old episodes of [callout]Tatort or Bukow & Konig[/callout].</p>\n<p>If I were teaching a music appreciation I wouldn't teach Beethoven. I'd teach Stamitz and average composers.</p>\n<p>And here is a 3rd paragraph.</p>\n<p>And here is a 4th paragraph.</p>"; 
$subst = "$1<blockquote class=\"pullquote\">Tatort or Bukow & Konig</blockquote>\n"; 
$result = preg_replace($re, $subst, $str, 1);

Demo is here.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-26
    • 2021-11-01
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 2016-07-13
    • 2014-06-10
    • 2020-10-10
    相关资源
    最近更新 更多