【问题标题】:PHP Find all occurrences of a substring in a stringPHP 查找字符串中所有出现的子字符串
【发布时间】:2013-03-22 04:06:29
【问题描述】:

我需要解析一个 HTML 文档并在其中找到所有出现的字符串 asdf

我目前已将 HTML 加载到字符串变量中。我只想要字符位置,这样我就可以遍历列表以在字符串之后返回一些数据。

strpos 函数只返回 first 出现。 全部返回怎么样?

【问题讨论】:

    标签: php string


    【解决方案1】:

    不使用正则表达式,这样的东西应该可以返回字符串位置:

    $html = "dddasdfdddasdffff";
    $needle = "asdf";
    $lastPos = 0;
    $positions = array();
    
    while (($lastPos = strpos($html, $needle, $lastPos))!== false) {
        $positions[] = $lastPos;
        $lastPos = $lastPos + strlen($needle);
    }
    
    // Displays 3 and 10
    foreach ($positions as $value) {
        echo $value ."<br />";
    }
    

    【讨论】:

    • 请小心在if 语句中使用赋值。在这种情况下,您的 while 循环不适用于位置 0。我已经更新了你的答案。
    • 很好的修复,但对于那些需要查找特殊字符(é、ë、...)的人,请将 strpos 替换为 mb_strpos,否则将无法正常工作
    • 所有将重用此代码的人都要小心,因为您的指针可能类似于“dd”,在这种情况下,$lastPos 应该只在 while 循环内增加 1。
    【解决方案2】:

    您可以重复调用strpos 函数,直到找不到匹配项。您必须指定偏移参数。

    注意:在以下示例中,搜索从 下一个 字符开始,而不是从上一个匹配项的结尾开始。根据这个函数,aaaa 包含 三个 出现的子字符串 aa,而不是两个。

    function strpos_all($haystack, $needle) {
        $offset = 0;
        $allpos = array();
        while (($pos = strpos($haystack, $needle, $offset)) !== FALSE) {
            $offset   = $pos + 1;
            $allpos[] = $pos;
        }
        return $allpos;
    }
    print_r(strpos_all("aaa bbb aaa bbb aaa bbb", "aa"));
    

    输出:

    Array
    (
        [0] => 0
        [1] => 1
        [2] => 8
        [3] => 9
        [4] => 16
        [5] => 17
    )
    

    【讨论】:

      【解决方案3】:

      最好使用substr_count。查看php.net

      【讨论】:

      • 这只会给你计数,而不是他们提出的问题的位置
      • "这个函数不计算重叠的子串。"对于字符串 'abababa',当您查看 'aba' 时,它只会计算 2 次而不是 3 次
      【解决方案4】:
      function getocurence($chaine,$rechercher)
              {
                  $lastPos = 0;
                  $positions = array();
                  while (($lastPos = strpos($chaine, $rechercher, $lastPos))!== false)
                  {
                      $positions[] = $lastPos;
                      $lastPos = $lastPos + strlen($rechercher);
                  }
                  return $positions;
              }
      

      【讨论】:

      • 纯代码答案在 StackOverflow 上的价值很低,因为它们对 OP 和未来的读者的教育作用很小。请编辑您的答案,以教育成千上万的未来 SO 读者和 OP。
      【解决方案5】:

      使用preg_match_all 查找所有个事件。

      preg_match_all('/(\$[a-z]+)/i', $str, $matches);
      

      更多参考请查看this link

      【讨论】:

      • 他正在寻找字符串位置,而不仅仅是匹配项。他还希望匹配“asdf”,而不是 [a-z]...
      【解决方案6】:

      这可以使用 strpos() 函数来完成。下面的代码是使用 for 循环实现的。这段代码非常简单而且非常直接。

      <?php
      
      $str_test = "Hello World! welcome to php";
      
      $count = 0;
      $find = "o";
      $positions = array();
      for($i = 0; $i<strlen($str_test); $i++)
      {
           $pos = strpos($str_test, $find, $count);
           if($pos == $count){
                 $positions[] = $pos;
           }
           $count++;
      }
      foreach ($positions as $value) {
          echo '<br/>' .  $value . "<br />";
      }
      
      ?>
      

      【讨论】:

        【解决方案7】:

        Salman A 有一个很好的答案,但请记住让您的代码具有多字节安全性。要使用 UTF-8 获得正确的位置,请使用 mb_strpos 而不是 strpos:

        function strpos_all($haystack, $needle) {
            $offset = 0;
            $allpos = array();
            while (($pos = mb_strpos($haystack, $needle, $offset)) !== FALSE) {
                $offset   = $pos + 1;
                $allpos[] = $pos;
            }
            return $allpos;
        }
        print_r(strpos_all("aaa bbb aaa bbb aaa bbb", "aa"));
        

        【讨论】:

          【解决方案8】:

          简单的strpos_all()函数。

          function strpos_all($haystack, $needle_regex)
          {
              preg_match_all('/' . $needle_regex . '/', $haystack, $matches, PREG_OFFSET_CAPTURE);
              return array_map(function ($v) {
                  return $v[1];
              }, $matches[0]);
          }
          

          用法: 像针一样简单的绳子。

          $html = "dddasdfdddasdffff";
          $needle = "asdf";
          
          $all_positions = strpos_all($html, $needle);
          var_dump($all_positions);
          

          输出:

          array(2) {
            [0]=>
            int(3)
            [1]=>
            int(10)
          }
          

          或者用正则表达式作为针。

          $html = "dddasdfdddasdffff";
          $needle = "[d]{3}";
          
          $all_positions = strpos_all($html, $needle);
          var_dump($all_positions);
          

          输出:

          array(2) {
            [0]=>
            int(0)
            [1]=>
            int(7)
          }
          

          【讨论】:

          • 使用正则表达式查找子字符串不是一个好方法。当然你可以这样做,但正则表达式适用于更复杂的场景。在这种情况下,使用strpos 会简单得多,并且可以完成工作。
          【解决方案9】:
          <?php
          $mainString = "dddjmnpfdddjmnpffff";
          $needle = "jmnp";
          $lastPos = 0;
          $positions = array();
          
          while (($lastPos = strpos($html, $needle, $lastPos))!== false) {
              $positions[] = $lastPos;
              $lastPos = $lastPos + strlen($needle);
          }
          
          // Displays 3 and 10
          foreach ($positions as $value) {
              echo $value ."<br />";
          }
          ?>
          

          【讨论】:

            【解决方案10】:

            另一种解决方案是使用explode():

            public static function allSubStrPos($str, $del)
            {
                $searchArray = explode($del, $str);
                unset($searchArray[count($searchArray) - 1]);
                $positionsArray = [];
                $index = 0;
                foreach ($searchArray as $i => $s) {
                    array_push($positionsArray, strlen($s) + $index);
                    $index += strlen($s) + strlen($del);
                }
                return $positionsArray;
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-12-23
              • 1970-01-01
              • 2012-10-12
              • 1970-01-01
              相关资源
              最近更新 更多