33

我有兴趣在function delete_all_between($char1, $char2, $string) 给定的 $string 中搜索 $char1 和 $char2 ,如果找到了,则从这两个字符之间的子字符串中清除 $string,包括$char1 和 $char2 本身。

例子:

$string = 'Some valid and <script>some invalid</script> text!';
delete_all_between('<script>', '</script>', $string);

现在, $string 应该只包含

'Some valid and  text'; //note two spaces between 'and  text'

有人有快速解决方案吗?

4

8 回答 8

62
<?php

$string = 'Some valid and <script>some invalid</script> text!';
$out = delete_all_between('<script>', '</script>', $string);
print($out);

function delete_all_between($beginning, $end, $string) {
  $beginningPos = strpos($string, $beginning);
  $endPos = strpos($string, $end);
  if ($beginningPos === false || $endPos === false) {
    return $string;
  }

  $textToDelete = substr($string, $beginningPos, ($endPos + strlen($end)) - $beginningPos);

  return delete_all_between($beginning, $end, str_replace($textToDelete, '', $string)); // recursion to ensure all occurrences are replaced
}
于 2012-10-23T13:28:52.040 回答
48

这是一个单线:

preg_replace('/START[\s\S]+?END/', '', $string);

替换STARTEND:) 学分转到另一个 SO 线程!

于 2015-12-10T09:50:40.617 回答
1

我觉得substr()工作太慢了。最好的方法是:

return substr($string, 0, $beginningPos) . 
       substr($string, $endPos + strlen($end));
于 2013-06-17T15:44:04.320 回答
1

在我的情况下,第一个版本有问题,这是我更正的版本(如果 $end 字符串也出现在 $beginning 字符串之前)

<?php 
$string = 'Some </script> valid and <script>some invalid</script> text!';
$out = delete_all_between('<script>', '</script>', $string);
print($out);

function delete_all_between($beginning, $end, $string) {
    $beginningPos = strpos($string, $beginning);
    $tmpstring = substr($string, $beginningPos);  
    $endPos = strpos($tmpstring, $end);
    if ($beginningPos === false || $endPos === false) {
        return $string;
    }
    $textToDelete = substr($string, $beginningPos, ($endPos + strlen($end)) );
    return delete_all_between($beginning, $end, str_replace($textToDelete, '', $string)); // recursion to ensure all occurrences are replaced
}
于 2021-07-23T16:13:41.830 回答
1

实际上,我一直在寻找一个函数,它为我提供了简单而稳定的解决方案来获取 TWIG 模板的所有变量。由于许多原因,建议的正则表达式效果不佳,所以我决定只删除标签之间的所有内容,而不是计算标签^_^。

/**
     * deletes ALL the string contents between all the designated characters
     * @param $start - pattern start 
     * @param $end   - pattern end
     * @param $string - input string, 
     * @return mixed - string
     */
    function auxDeleteAllBetween($start, $end, $string) {
        // it helps to assembte comma dilimited strings
        $string = strtr($start. $string . $end, array($start => ','.$start, $end => chr(2)));
        $startPos  = 0;
        $endPos = strlen($string);
        while( $startPos !== false && $endPos !== false){
            $startPos = strpos($string, $start);
            $endPos = strpos($string, $end);
            if ($startPos === false || $endPos === false) {
                $run = false;
                return $string;
            }
            $textToDelete = substr($string, $startPos, ($endPos + strlen($end)) - $startPos);
            $string = str_replace($textToDelete, '', $string);
        }
        return $string;
    }

    /**
     * This function is intended to replace
     * //preg_match_all('/\{\%\s*([^\%\}]*)\s*\%\}|\{\{\s*([^\}\}]*)\s*\}\}/i', $this->_tplSubj, $matchesSubj);
     * which did not give intended results for some reason.
     *
     * @param $inputTpl
     * @return array
     */
    private function auxGetAllTags($inputTpl){
        $inputTpl = strtr($inputTpl, array('}}' => ','.chr(1), '{{' => chr(2)));
        return explode(',',$this->auxDeleteAllBetween(chr(1),chr(2),$inputTpl));
    }


$template = '<style>
td{border-bottom:1px solid #eee;}</style>
<p>Dear {{jedi}},<br>New {{padawan}} is waiting for your approval: </p>
<table border="0">
<tbody><tr><td><strong>Register as</strong></td><td>{{register_as}}, user-{{level}}</td></tr>
<tr><td><strong>Name</strong></td><td>{{first_name}} {{last_name}}</td></tr>...';

print_r($this->auxGetAllTags($template));
于 2016-05-23T00:02:53.650 回答
0

我想删除 php 中的标签,因为我想在将 html 解析为 DOMDocument 之前删除未使用的标签。

这是我使用的代码。光标在开始时为 0。它只是用于程序中的递归。

function delete_all_betweenV2($cursor, $beginning, $end, $string, $retainSelf) {
    echo '>>>> Start '.'<br>';
    $beginningPos = strpos($string, $beginning, $cursor);
    $endPos = strpos($string, $end, $beginningPos);
    
    if ($beginningPos === false || $endPos === false) {
      echo '>>>> End '.'<br>';
      return $string;
    }    
    
    if($endPos >= strlen($string)) {
      echo '>>>> End '.'<br>';
      return $string;
    }
    
    $lenOfBeginning = strlen($beginning);
    $lenOfEnd = strlen($end);
    
    $result = $string;
    if($retainSelf) {
      echo 'b4 input String: '.$string.'<br>';
      echo 'b4 cursor = : '.$cursor. '<br>';
      echo 'b4 string: '.$string. '<br>';
      echo 'b4 beginning Pos: '.$beginningPos.'<br>';
      echo 'b4 end Pos: '.$endPos.'<br>';
      echo 'b4 length to be cut is: '.(($endPos - $lenOfEnd) - $beginningPos).'<br>';
      
      if($cursor > 0) {
        echo 'cursor is greater than 0'.'<br>';
        $textToDelete = substr($string, $beginningPos + $lenOfBeginning, ($endPos - $lenOfEnd) - $beginningPos);
      } else {
        echo 'cursor is NOT greater than 0'.'<br>';
        $textToDelete = substr($string, $beginningPos + $lenOfBeginning, ($endPos - $lenOfEnd) - $beginningPos);
      }
      
      echo 'TextToDelete:'.$textToDelete.'<br>';
        
      //$stringStart = substr($string, 0, $beginningPos + $lenOfBeginning);
      //echo $stringStart.'<br>';
      //$stringTail = substr($string, $endPos, strlen($string));
      //echo $stringTail.'<br>';    
      $result = str_replace($textToDelete, '', $string);
      $cursor = $beginningPos + $lenOfBeginning; // just make sure that the cursor search next character/word
      echo 'After cursor = : '.$cursor. '<br>';
      echo 'After result: '.$result. '<br>';
      echo 'After len of result: '.strlen($result). '<br>';
    } else {
        //$stringStart = substr($string, 0, $beginningPos);
        //echo $stringStart.'<br>';
        //$stringTail = substr($string, $endPos + $lenOfEnd, strlen($string));
        //echo $stringTail.'<br>';
        $cursor = 0;
        
        $textToDelete = substr($string, $beginningPos, ($endPos + $lenOfEnd) - $beginningPos);
        echo 'TextToDelete:'.$textToDelete.'<br>';
        $result = str_replace($textToDelete, '', $string);
    } 
    echo '>>>> End '.'<br>';
    return delete_all_betweenV2($cursor, $beginning, $end, $result, $retainSelf);
}
于 2021-05-08T08:17:12.670 回答
0

作为对 AndreaTS 的 delete_all_between() 的修订,但为了处理标签属性(例如<script type='abc'>)和不区分大小写,我有这个......

    function delete_all_between(string $html, string $tag) {
        $startTag="<$tag ";
        $endTag="</$tag>";
        $html     =str_ireplace("<$tag>", "<$tag >", $html);
        $startPos = stripos($html, $startTag);
        $tmpStr = substr($html, $startPos);
        $endPos = stripos($tmpStr, $endTag);
        if ($startPos === false || $endPos === false) {
            return $html;
        }
        $textToDelete = substr($html, $startPos, ($endPos + strlen($startTag))+1 );
        return delete_all_between(str_replace($textToDelete, '', $html), $tag); // recursion to ensure all occurrences are replaced
    }

请参阅http://sandbox.onlinephpfunctions.com/code/1b984b61cfd1c9cea4c6eef1d765ff387a4cd9e9了解运行此的 php 沙箱。

于 2021-10-13T13:08:59.983 回答
-2

您可以使用双 str_replace() $q = str_replace('<script>', '', $string); $p = str_replace('some invalid', '', $q); echo $p;

于 2018-01-04T11:41:19.453 回答