【问题标题】:Simple: How to replace "all between" with php? [duplicate]简单:如何用php替换“所有之间”? [复制]
【发布时间】:2011-10-16 02:19:24
【问题描述】:
$string = "<tag>i dont know what is here</tag>"
$string = str_replace("???", "<tag></tag>", $string);
echo $string; // <tag></tag>

那么我在寻找什么代码?

【问题讨论】:

    标签: php replace str-replace


    【解决方案1】:

    一个通用函数:

    function replace_between($str, $needle_start, $needle_end, $replacement) {
        $pos = strpos($str, $needle_start);
        $start = $pos === false ? 0 : $pos + strlen($needle_start);
    
        $pos = strpos($str, $needle_end, $start);
        $end = $pos === false ? strlen($str) : $pos;
    
        return substr_replace($str, $replacement, $start, $end - $start);
    }
    

    DEMO

    【讨论】:

    • 比接受的答案更好。除非您需要,否则无需使用正则表达式替换。
    • @sgroves 正则表达式在避免代码卷积或提供另一个明显优势时是一个合理的工具。
    • 我在 PHP 7 中尝试过,但没有回显结果,似乎它也在剥离标签 - 我想知道是否有一个适用于所有事件的选项,即超过 1 组标签之间的文字
    • 更好的解决方案!
    【解决方案2】:
    $search = "/[^<tag>](.*)[^<\/tag>]/";
    $replace = "your new inner text";
    $string = "<tag>i dont know what is here</tag>";
    echo preg_replace($search,$replace,$string);
    

    输出:

    <tag>your new inner text</tag>
    

    【讨论】:

    • 我假设您要替换标签的内容,而不仅仅是替换整个字符串。
    • 老实说应该使用环视。
    • 按原样运行此代码,我得到Warning: preg_replace() [function.preg-replace]: Unknown modifier 't' on line 1
    • 这个答案 100% 不正确。它提供所需的输出只是偶然的。当输入略有变化时,请注意此答案失败。 3v4l.org/p507L 这是对否定字符类的错误使用,它误导了研究人员。 @常见问题
    • 如果您觉得有更好的答案提供它,但我绝不会说这个答案是“100% 不正确”,因为它完全符合编写时需要做的事情(和 OP 明确同意)。
    【解决方案3】:
    $string = "<tag>I do not know what is here</tag>";
    $new_text = 'I know now'; 
    echo preg_replace('#(<tag.*?>).*?(</tag>)#', '$1'.$new_text.'$2' , $string); //<tag>I know now</tag>
    

    【讨论】:

    • 您在第二个参数中缺少替换字符串:'$1'.'new text'.'$2'
    【解决方案4】:

    如果“标签”发生变化:

    $string = "<tag>i dont know what is here</tag>";
    $string = preg_replace('|^<([a-z]*).*|', '<$1></$1>', $string)
    echo $string; // <tag></tag>
    

    【讨论】:

    • 优秀的解决方案
    【解决方案5】:
    $string = "<tag>i dont know what is here</tag>"
    $string = "<tag></tag>";
    echo $string; // <tag></tag>
    

    还是只是?

    $string = str_replace($string, "<tag></tag>", $string);
    

    对不起,忍不住了。也许你用更多细节更新你的问题。 ;)

    【讨论】:

      【解决方案6】:

      如果您不知道 &lt;tag&gt; 标记内的内容,则可能还有另一个 &lt;tag&gt; 标记,例如

      <tag>something<tag>something else</tag></tag>
      

      所以一个通用的字符串替换函数将无法完成这项工作。

      更强大的解决方案是将字符串视为 XML 并使用DOMDocument 对其进行操作。诚然,这仅在字符串作为 XML 有效时才有效,但我仍然认为它是比字符串替换更好的解决方案。

      $string = "<tag>i don't know what is here</tag>";
      $replacement = "replacement";
      
      $doc = new DOMDocument();
      $doc->loadXML($str1);
      $node = $doc->getElementsByTagName('tag')->item(0);
      $newNode = $doc->createElement("tag", $replacement); 
      $node->parentNode->replaceChild($newNode, $node);
      echo $str1 = $doc->saveHTML($node); //output: <tag>replacement</tag>
      

      【讨论】:

      • 这几乎是一个可行的答案。我做了一些调整。 3v4l.org/phEOf 总体来说,如果DomDocument可以用的话,应该是为了稳定才用的。
      【解决方案7】:

      通用且非正则表达式的解决方案:

      我修改了@felix-kling 的答案。现在它只在找到针时替换文本。

      另外,我添加了更换针头、起始位置和更换所有火柴的参数。

      我使用了mb_ 函数来使函数多字节安全。 如果您需要不区分大小写的解决方案,请将 mb_strpos 调用替换为 mb_stripos

      function replaceBetween($string, $needleStart, $needleEnd, $replacement,
                              $replaceNeedles = false, $startPos = 0, $replaceAll = false) {
          $posStart = mb_strpos($string, $needleStart, $startPos);
      
          if ($posStart === false) {
              return $string;
          }
      
          $start = $posStart + ($replaceNeedles ? 0 : mb_strlen($needleStart));
          $posEnd = mb_strpos($string, $needleEnd, $start);
      
          if ($posEnd === false) {
              return $string;
          }
      
          $length = $posEnd - $start + ($replaceNeedles ? mb_strlen($needleEnd) : 0);
      
          $result = substr_replace($string, $replacement, $start, $length);
      
          if ($replaceAll) {
              $nextStartPos = $start + mb_strlen($replacement) + mb_strlen($needleEnd);
      
              if ($nextStartPos >= mb_strlen($string)) {
                  return $result;
              }
      
              return replaceBetween($result, $needleStart, $needleEnd, $replacement, $replaceNeedles, $nextStartPos, true);
          }
      
          return $result;
      }
      
      $string = "{ Some} how it {is} here{";
      
      echo replaceBetween($string, '{', '}', '(hey)', true, 0, true); // (hey) how it (hey) here{
      

      【讨论】:

        【解决方案8】:

        如果您也需要更换该部分,那么此功能很有帮助:

        $var = "Nate";
        
        $body = "Hey there {firstName} have you already completed your purchase?";
        
        $newBody = replaceVariable($body,"{","}",$var);
        
        echo $newBody;
        
        function replaceVariable($body,$needleStart,$needleEnd,$replacement){
          while(strpos($body,$needleStart){
              $start = strpos($body,$needleStart);
              $end = strpos($body,$needleEnd);
              $body = substr_replace($body,$replacement,$start,$end-$start+1);
          }
          return $body;
        }
        

        我必须替换放入已提交的文本区域的变量。所以我用 Nate 替换了 firstName(包括花括号)。

        【讨论】:

        • 这很好用,没有正则表达式。但前提是您只想替换一次出现的字符串。如果你需要替换多个出现,你必须做一个循环,直到 strpos 将返回 FALSE (这意味着没有任何出现可以替换。
        • 注意:这个表达式 strpos($body,$needleEnd); 将从字符串的开头开始搜索。要从起始针开始搜索,您需要一个偏移量:strpos($body,$needleEnd, $needleStart);.
        猜你喜欢
        • 2011-08-04
        • 1970-01-01
        • 2011-11-30
        • 1970-01-01
        • 1970-01-01
        • 2011-10-21
        • 1970-01-01
        • 2013-11-01
        • 1970-01-01
        相关资源
        最近更新 更多