" and "& lt" with "<" but only when they occur...">

Regex replace text only when happens outside of two lines?

I would like to replace "& gt" with ">" and "& lt" with "<" but only when they occur outside of "<pre>" and "</pre>". Is it possible?

$newText = preg_replace('&gt', '>', $text);

      

I would use preg_replace in PHP as above.

+1


source to share


3 answers


If you want to do this with a regex, the trick is to make your regex match what you don't want to replace, and the things you want to replace, and dynamically compute the replacement based on what was matched.



$new_text = preg_replace_callback('%&lt;|&gt;|<pre>.*?</pre>%si', compute_replacement, $text);

function compute_replacement($groups) {
    if ($groups[0] == '&lt;') {
      return '<';
    } elseif ($groups[1] == '&gt;') {
      return '>';
    } else {
      return $groups[0];
    }
}

      

+2


source


This is not really an answer because you asked for a regex, but I just wrote a really dirty function:



<?php

$html = ' <pre>hello &gt; &lt;</pre>
            &gt; &lt;
            <pre></pre>';


function stringReplaceThing($str) {
    $offset = 0;
    $num = 0;
    $preContents = array();
    $length = strlen($str);

    //copy string so can maintain offsets/positions in the first string after replacements are made
    $str2=$str;

    //get next position of <pre> tag
    while (false !== ($startPos = stripos($str, '<pre>', $offset))) {
        //the end of the opening <pre> tag
        $startPos += 5;

        //try to get closing tag
        $endPos = stripos($str, '</pre>', $startPos);

        if ($endPos === false) {
            die('unclosed pre tag..');
        }

        $stringWithinPreTags = substr($str, $startPos, $endPos - $startPos);
        //replace string within tags with some sort of token
        if (strlen($stringWithinPreTags)) {
            $token = "!!T{$num}!!";
            $str2 = str_replace($stringWithinPreTags, $token, $str2);
            $preContents[$token] = $stringWithinPreTags;
            $num++;
        }

        $offset = $endPos + 5;
    }

    //do the actual replacement
    $str2 = str_replace(array('&gt;', '&lt;'), array('>', '<'), $str2);

    //put the contents of <pre></pre> blocks back in
    $str2 = str_replace(array_keys($preContents), array_values($preContents), $str2);
    return $str2;
}


print stringReplaceThing($html);

      

+3


source


I'm not sure if the PHP regex engine will do negative imagery, but that's what you're interested in. Regular expression in other languages ​​will look something like this:

/(?<!(<pre>[^(<\/pre>)]*))XXX(?!(.*<\/pre>))/

      

(inhale - I think I have this right)

where XXX is your pattern "<" or ">"

p. there is probably an even simpler pattern.

0


source







All Articles