【问题标题】:How do you perform a preg_match where the pattern is an array, in php?你如何在php中执行模式是数组的preg_match?
【发布时间】:2009-03-25 22:09:31
【问题描述】:

我有一个充满了我需要匹配的模式的数组。除了 for() 循环之外,还有什么方法可以做到这一点?我试图以 CPU 密集度最低的方式来做这件事,因为我每分钟都会做几十个这样的事情。

现实世界的例子是,我正在构建一个链接状态检查器,它将检查各种在线视频网站的链接,以确保视频仍然处于活动状态。每个域都有几个“死关键词”,如果在页面的 html 中找到这些,则意味着该文件已被删除。这些存储在数组中。我需要将数组的内容与页面的 html 输出相匹配。

【问题讨论】:

    标签: php arrays preg-match


    【解决方案1】:

    首先,如果您实际上每 分钟 只执行 几十次,那么我不会非常担心这种情况下的性能。这些匹配非常快,我认为通过遍历您的模式数组并像这样单独调用 preg_match 不会出现性能问题:

    $matches = false;
    foreach ($pattern_array as $pattern)
    {
      if (preg_match($pattern, $page))
      {
        $matches = true;
      } 
    }
    

    您确实可以像某些人建议的那样使用or 运算符将所有模式组合成一个,但不要只是将它们与| 一起拍打。如果您的任何模式包含 or 运算符,这将严重破坏。

    我建议至少使用括号对您的模式进行分组,例如:

    foreach ($patterns as $pattern)
    {
      $grouped_patterns[] = "(" . $pattern . ")";
    }
    $master_pattern = implode($grouped_patterns, "|");
    

    但是...我不确定这最终是否会更快。 某些东西 必须循环遍历它们,无论是 preg_match 还是 PHP。如果我不得不猜测,我会猜测单个匹配会接近相同的速度,并且更易于阅读和维护。

    最后,如果性能是您在这里寻找的,我认为最重要的事情是将非正则表达式匹配提取到一个简单的“字符串包含”检查中。我想您的某些检查必须是简单的字符串检查,例如查看“此站点已关闭”是否在页面上。

    这样做:

    foreach ($strings_to_match as $string_to_match)
    {
      if (strpos($page, $string_to_match) !== false))
      {
        // etc.
        break;
      }
    }
    foreach ($pattern_array as $pattern)
    {
      if (preg_match($pattern, $page))
      {
        // etc.
        break;
      } 
    }
    

    并避免尽可能多的preg_match() 可能是您最大的收获。 strpos()preg_match()很多

    【讨论】:

    • 为了 Google 员工,一旦找到匹配项,请考虑使用 break (php.net/manual/en/control-structures.break.php) 来跳出 foreach 循环!
    • 我相信这应该是: foreach ($pattern_array as $pattern) ,至少在我的 PHP 版本中
    • 好吧,你们...编辑以解决您的 cmets。
    • foreach ($patterns as $pattern) { $grouped_patterns[] = "(" . $pattern . ")"; } $master_pattern = implode($grouped_patterns, "|"); 可以写成一行代码:$master_pattern = '/(' . implode($patterns, ')|(') . ')/'
    • 小记..我认为implode应该有一个字符串作为第一个参数和数组作为第二个。
    【解决方案2】:
    // assuming you have something like this
    $patterns = array('a','b','\w');
    
    // converts the array into a regex friendly or list
    $patterns_flattened = implode('|', $patterns);
    
    if ( preg_match('/'. $patterns_flattened .'/', $string, $matches) )
    {
    }
    
    // PS: that's off the top of my head, I didn't check it in a code editor
    

    【讨论】:

    • 在“模式”周围没有括号/括号的情况下是否可以工作?
    【解决方案3】:

    如果您的模式不包含很多空格,另一种选择是避开数组并使用/x 修饰符。现在您的正则表达式列表将如下所示:

    $regex = "/
    pattern1|   # search for occurences of 'pattern1'
    pa..ern2|   # wildcard search for occurences of 'pa..ern2'
    pat[ ]tern| # search for 'pat tern', whitespace is escaped
    mypat       # Note that the last pattern does NOT have a pipe char
    /x";
    

    使用/x 修饰符,空格将被完全忽略,除非在字符类中或前面有反斜杠。上面的评论也是允许的。

    这样可以避免遍历数组。

    【讨论】:

      【解决方案4】:

      如果您只是在另一个字符串中搜索某个字符串是否存在,请使用 strpos,因为它更快。

      否则,您可以遍历模式数组,每次调用 preg_match。

      【讨论】:

        【解决方案5】:

        如果你有一堆模式,你可以做的就是将它们连接到一个正则表达式中并匹配它。不需要循环。

        【讨论】:

          【解决方案6】:

          如何在使用数组获得的 HTML 上执行str_replace(),然后检查原始 HTML 是否等于原始 HTML?这会非常快:

           $sites = array(
                'you_tube' => array('dead', 'moved'),
                ...
           );
           foreach ($sites as $site => $deadArray) {
               // get $html
               if ($html == str_replace($deadArray, '', $html)) { 
                   // video is live
               }
           }
          

          【讨论】:

          • 如果您想要完全匹配,str_replace 不起作用
          【解决方案7】:

          您可以使用implode() php 函数将列表中的所有模式组合成单个正则表达式。然后使用preg_match() php 函数立即测试您的字符串。

          $patterns = array(
            'abc',
            '\d+h',
            '[abc]{6,8}\-\s*[xyz]{6,8}',
          );
          
          $master_pattern = '/(' . implode($patterns, ')|(') . ')/'
          
          if(preg_match($master_pattern, $string_to_check))
          {
            //do something
          }
          

          当然,在“if()”条件下使用 implode() 内联代码而不是 $master_pattern 变量当然可以更少代码。

          【讨论】:

          • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
          • 添加了几个解释。
          猜你喜欢
          • 1970-01-01
          • 2011-06-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-05
          • 2013-07-12
          相关资源
          最近更新 更多