【问题标题】:Regex to find sequential integers正则表达式查找顺序整数
【发布时间】:2011-06-03 14:11:46
【问题描述】:

我很难让我的正则表达式代码在 PHP 中正常工作。这是我的代码:

$array = array(); // Used to satisfy the 3rd argument requirment of preg_match_all.
$regex = '/(012|345|678|987|654|321|123|456|789|876|543|210|234|567|765|432)/';
$subject = '123456';
echo preg_match_all($regex, $subject, $array).'<br />';
print_r($array);

这段代码运行时会输出:

2
Array
(
    [0] => Array
        (
            [0] => 123
            [1] => 456
        )
    [1] => Array
        (
            [0] => 123
            [1] => 456
        )
)

我该怎么做才能匹配 123、234、345 和 456?

提前致谢!

【问题讨论】:

  • | (pipe) 使正则表达式引擎匹配左侧的部分或右侧的部分。可以串成一系列选项。

标签: php regex overlapping-matches


【解决方案1】:

Regex 不是这项工作的正确工具(它不会返回“子匹配项”)。只需在循环中使用strpos

$subject = '123456';

$seqs = array('012', '345', '678', '987', '654', '321', '123', '456', '234');
foreach ($seqs as $seq) {
    if (strpos($subject, $seq) !== false) {
        // found
    }
}

【讨论】:

    【解决方案2】:
    $regex = '/(?=(012|345|678|987|654|321|123|456|789|876|543|210|234|567|765|432))/';
    $subject = '123456';
    preg_match_all($regex, $subject, $array);
    print_r($array[1]);
    

    输出:

    Array
    (
        [0] => 123
        [1] => 234
        [2] => 345
        [3] => 456
    )
    

    您正在尝试检索在主题字符串中相互重叠的匹配项,这通常是不可能的。但是,在许多情况下,您可以通过将整个正则表达式包装在捕获组中,然后将其包装在前瞻中来伪造它。因为前瞻在匹配时不消耗任何字符,所以正则表达式引擎在每次成功匹配后手动向前移动一个位置,以避免陷入无限循环。但是捕获组仍然有效,因此您可以按常规方式检索捕获的文本。

    请注意,我只打印了第一个捕获组 ($array[1]) 的内容。如果我打印了整个数组数组 ($array),它会是这样的:

    Array
    (
        [0] => Array
        (
            [0] => 
            [1] => 
            [2] => 
            [3] => 
        )
    
        [1] => Array
        (
            [0] => 123
            [1] => 234
            [2] => 345
            [3] => 456
        )
    )
    

    see it in action on ideone

    【讨论】:

      【解决方案3】:

      可以用正则表达式来完成。您的原始代码的问题是,一旦发生匹配,字符就会被消耗,并且正则表达式不会回溯。这是一种方法:

      $array = array(); // Used to satisfy the 3rd argument requirment of preg_match_all.
      $regex = '/012|345|678|987|654|321|123|456|789|876|543|210|234|567|765|432/';
      $subject = '123456';
      
      $tempSubject = $subject;
      $finalAnswer = array();
      do {
          $matched = preg_match($regex, $tempSubject, $array);
          $finalAnswer = array_merge($finalAnswer, $array);
          $tempSubject = substr($tempSubject, 1);
      } while ($matched && (strlen($tempSubject >= 3)));
      print_r($finalAnswer);
      

      但是,正如另一个答案中所建议的那样,正则表达式可能不是在这种情况下使用的正确工具,具体取决于您的更大目标。另外,上面的代码可能不是用正则表达式解决这个问题的最有效方法(wrt memory 或 wrt performance)。这只是一个简单的满足需求的解决方案。

      【讨论】:

        【解决方案4】:

        是的,这是一个 hack,但你可以使用 RegEx

        <?php
        $subject = '123456';
        
        $rs = findmatches($subject);
        echo '<pre>'.print_r($rs,true).'</pre><br />';
        
        
        function findmatches($x) {
            $regex = '/(\d{3})/'; 
        
            // Loop through the subject string
            for($counter =  0; $counter <= strlen($x); $counter++) {
                $y = substr($x, $counter);
                if(preg_match_all($regex, $y, $array)) {
                    $rs_array[$counter] = array_unique($array);
                }
            }
        
            // Parse results array
            foreach($rs_array as $tmp_arr) {
                $rs[] = $tmp_arr[0][0];
            }
            return $rs;
        }
        ?>
        

        返回:

        Array
        (
            [0] => 123
            [1] => 234
            [2] => 345
            [3] => 456
        )
        

        注意:这仅适用于并发数

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-30
          • 1970-01-01
          • 2023-02-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多