PHP Regex expression excluding <pre> tag

拥有回忆 提交于 2021-02-05 07:10:45

问题


I am using a WordPress plugin named Acronyms (https://wordpress.org/plugins/acronyms/). This plugin replaces acronyms with their description. It uses a PHP PREG_REPLACE function.

The issue is that it replaces the acronyms contained in a <pre> tag, which I use to present a source code.

Could you modify this expression so that it won't replace acronyms contained inside <pre> tags (not only directly, but in any moment)? Is it possible?

The PHP code is:

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

回答1:


You can use a PCRE SKIP/FAIL regex trick (also works in PHP) to tell the regex engine to only match something if it is not inside some delimiters:

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

This means: skip all substrings starting with <pre> and ending with </pre>, and only then match $acronym as a whole word.

See demo on regex101.com

Here is a 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;

Output:

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



回答2:


It is also possible to use preg_split and keep the code block as a group, only replace the non-code block part then combine it back as a complete string:

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;

Taken from here.



来源:https://stackoverflow.com/questions/30120859/php-regex-expression-excluding-pre-tag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!