如何使用PHP替换<pre>标签外的\r\n而不是内部的\r\n

4

我有一个字符串,例如:

This is text outside \r \n of pre tags 
<pre class="myclass"> Text inside \r \n pre tags</pre> 
This is text \r \n  \r\n outside of pre tags

请问有谁能帮我解决如何替换和删除 \r \n,但是只在 <pre> 标签之外(<pre class="myclass"></pre> 内容不会被替换)?

如何使用 PHP 正则表达式和 preg_replace() 或其他方法实现?

我有一个变量中的文本 $text = 'text<pre class="myclass">text</pre>text';

非常感谢您的帮助。

更新: 感谢大家的回复,对我很有帮助,我会考虑 DOM,我已经尝试过 preg_split(),似乎可以满足我的需求,也许对别人有用 - 替换 <pre class="myclass"></pre> 标签之外的 \r\n:

 function ReplaceOutsidePreTags($text) {
         $parts = preg_split('/(\<pre class="myclass"\>.+?\<\/pre\>)/s',$text,-1,PREG_SPLIT_DELIM_CAPTURE);
         $text_new =  '';
         foreach ($parts as $key=>$value) {
           if (preg_match('[<pre class="myclass">|</pre>]',$value) == true) { 
              $text_new .= $value;  
           } else {
            $text_new .= str_replace(array("\\r\\n","\\n","\\r"),array("","",""), $value);
           } 
      }
     return $text_new;  
   }

 $text = 'this is text\r\n\r\r\n\n outside pre tag\r\n 
     <pre class="myclass">graphics,\r\n\r\nprogramming </pre>
     this is text outside\r\n pre tag\r\n  
     <pre class="myclass">graphics,\r\n\r\nprogramming </pre>
     this is text outside\r\n pre tag\r\n 
     <pre class="myclass">graphics,\r\n\r\nprogramming </pre>
     this is text outside pre tag\r\n';


           $text_new = $this->ReplaceOutsidePreTags($text);
        echo $text_new;

结果>

this is text outside pre tag 
     <pre class="myclass">graphics,\r\n\r\nprogramming </pre>
     this is text outside pre tag  
     <pre class="myclass">graphics,\r\n\r\nprogramming </pre>
     this is text outside pre tag 
     <pre class="myclass">graphics,\r\n\r\nprogramming </pre>
     this is text outside pre tag

4
这不是一个正则表达式任务。请参考以下链接了解如何在PHP中解析HTML:https://dev59.com/questions/EnA65IYBdhLWcg3w4C-j - user1919238
使用DOMDocument。查找所有文本节点。检查它是否有一个父节点是<pre>标签。相应地采取行动。获利。 - EJTH
2个回答

1

通用的“替换某些内容,但不在其他内容内部替换”的解决方案:

$out = preg_replace("(<pre(?:\s+\w+(?:=\w+|\"[^\"]+\"|'[^']+')?)*>.*?</pre>(*SKIP)(*FAIL)"
           ."|\r|\n)is", "", $in);

匹配带有属性的
标签(属性可以是布尔值、未引用、单引号或双引号,因为HTML没有反斜杠转义来复杂化问题),然后跳过并失败它们。然后匹配换行符并用空字符串替换它们。
然而,作为一个更一般的规则,考虑研究DOMDocument等DOM解析系统。迭代节点,忽略
标签,并从剩余的文本节点中删除换行符。
实际上,我使用与上面类似的正则表达式来保留重要位置的空格并从其他位置删除空格,但我使用...标记来避免HTML解析的丑陋 - 因为用户提供的内容是HTML转义的,所以它不会与注释冲突,因此没有问题。
编辑: 供参考,这里是我正在使用的代码,它通过预压缩空格每天为我节省了几兆字节到几千兆字节的带宽。我称之为“预压缩空格”。
$c = preg_replace_callback(
    "(<!-- WSP_BEGIN -->(.*?)<!-- WSP_END -->|\r|\n|\t)",
    function($m) {
        if( $m[1]) return $m[1]; // effectively strips markers
        else return " "; // condense whitespace
    },
    $c
);

0

在 PHP 中,实际上可以不使用正则表达式来进行工作:

//we need the string we want to fix, and the 2 limits of the substring we don't want to edit.
function get_string($string, $start, $end){
    //split until '<pre class="myclass">'
    $parts = explode($start,$string);
    //split the remaining part until </pre>
    $parts1 = explode($end,$parts[1]);
    //replace the 2 parts and build an array with the new strings
    $parts[0] = str_replace(array("\n","\r"),array("",""),$parts[0]);
    $parts[1] = $parts1[0];
    $parts[2] = str_replace(array("\n","\r"),array("",""),$parts1[1]);
    return implode(" ", $parts);
}

$fullstring = 'This is text outside \r \n of pre tags 
<pre class="myclass"> Text inside \r \n pre tags</pre> 
This is text \r \n  \r\n outside of pre tags';

$replaced = get_string($fullstring, '<pre class="myclass">', '</pre>');

谢谢,很有帮助,但如果文本中有更多的pre标签,它将无法工作。 - petran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接