【问题标题】:PHP Regex expression excluding <pre> tagPHP 正则表达式不包括 <pre> 标签
【发布时间】:2015-05-08 09:51:48
【问题描述】:

我正在使用一个名为 Acronyms (https://wordpress.org/plugins/acronyms/) 的 WordPress 插件。这个插件用他们的描述替换了首字母缩略词。它使用 PHP PREG_REPLACE 函数。

问题在于它替换了&lt;pre&gt; 标签中包含的首字母缩略词,我用它来展示源代码。

您能否修改此表达式,使其不会替换包含在 &lt;pre&gt; 标记中的首字母缩略词(不仅直接,而且在任何时候)?有可能吗?

PHP代码是:

$text = preg_replace(
    "|(?!<[^<>]*?)(?<![?.&])\b$acronym\b(?!:)(?![^<>]*?>)|msU"
  , "<acronym title=\"$fulltext\">$acronym</acronym>"
  , $text
);

【问题讨论】:

  • 感谢 collapsar 的代码风格!

标签: php regex wordpress replace pre


【解决方案1】:

您可以使用 PCRE SKIP/FAIL regex trick(也适用于 PHP)告诉正则表达式引擎仅匹配不在某些分隔符内的内容:

(?s)<pre[^<]*>.*?<\/pre>(*SKIP)(*F)|\b$acronym\b

这意味着:跳过所有以&lt;pre&gt; 开头并以&lt;/pre&gt; 结尾的子字符串,然后才将$acronym 作为一个完整的单词进行匹配。

demo on regex101.com

这是sample PHP demo

<?php
$acronym = "ASCII";
$fulltext = "American Standard Code for Information Interchange";
$re = "/(?s)<pre[^<]*>.*?<\\/pre>(*SKIP)(*F)|\\b$acronym\\b/"; 
$str = "<pre>ASCII\nSometext\nMoretext</pre>More text \nASCII\nMore text<pre>More\nlines\nASCII\nlines</pre>"; 
$subst = "<acronym title=\"$fulltext\">$acronym</acronym>"; 
$result = preg_replace($re, $subst, $str);
echo $result;

输出:

<pre>ASCII</pre><acronym title="American Standard Code for Information Interchange">ASCII</acronym><pre>ASCII</pre>

【讨论】:

  • 谢谢。这适用于单行字符串。包含在
     标记中但多于一行(包含换行符)的字符串呢?
  • OK,正则表达式、代码、链接和程序已更新。我用[^&lt;]* 进行了测试,它不需要(?s) 多行标志,但我认为你可以在&lt;pre&gt; 内有&lt;,所以切换到点,忘记添加标志:(
  • 像魅力一样工作!非常感谢你! :)
【解决方案2】:

也可以使用preg_split并将代码块保持为一个组,只替换非代码块部分,然后将其组合成一个完整的字符串:

function replace($s) {
    return str_replace('"', '&quot;', $s); // do something with `$s`
}

$text = 'Your text goes here...';
$parts = preg_split('#(<\/?[-:\w]+(?:\s[^<>]+?)?>)#', $text, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$text = "";
$x = 0;
foreach ($parts as $v) {
    if (trim($v) === "") {
        $text .= $v;
        continue;
    }
    if ($v[0] === '<' && substr($v, -1) === '>') {
        if (preg_match('#^<(\/)?(?:code|pre)(?:\s[^<>]+?)?>$#', $v, $m)) {
            $x = isset($m[1]) && $m[1] === '/' ? 0 : 1;
        }
        $text .= $v; // this is a HTML tag…
    } else {
        $text .= !$x ? replace($v) : $v; // process or skip…
    }
}

return $text;

取自here

【讨论】:

    猜你喜欢
    • 2015-07-19
    • 2014-06-19
    • 1970-01-01
    • 2013-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多