2008-11-19 4 views

Répondre

2

Si vous voulez faire ceci avec une regex, l'astuce consiste à faire correspondre votre regex avec les choses que vous ne voulez pas remplacer ainsi que les choses que vous voulez remplacer, et calculer dynamiquement le remplacement en fonction de ce qui a été apparié.

$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]; 
    } 
} 
0

Je ne suis pas désinvolture que si le moteur de regex PHP ne lookarounds négatif, mais c'est ce que vous êtes intéressé par le regex dans d'autres langues ressemblerait à quelque chose comme:.

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

(inspirez - Je pense J'ai ce droit)

où XXX est votre modèle "<" ou ">"

nb. il est probable qu'il ya un modèle encore plus simple trop

+0

Malheureusement php regex ne vous permet pas de mettre des affirmations et préanalyse lookbehind à l'intérieur d'une classe de caractères. Je n'ai pas testé votre code ci-dessus mais cela ressemble à un cauchemar de compilation (au moins en PHP). Aussi php nécessite que vos assertions soient fixées en largeur. – localshred

3

Ce n'est pas vraiment une réponse parce que vous avez demandé une expression régulière, mais je viens d'écrire une fonction vraiment sale de le faire:

<?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); 
+0

Parce que regex en php ne permet pas les assertions de largeur variable, je pense que cette approche est probablement la plus intelligente. C'est certainement plus pratique, mais toutes les autres tentatives que j'ai faites pour trouver une réponse regex ne résolvent pas complètement le problème. Je vais continuer à travailler dessus, ne vous inquiétez pas :). – localshred

Questions connexes