preg_match显示foreach循环中的第一个匹配项

时间:2012-06-26 12:36:37

标签: php regex preg-match

我有一系列模式:

$patterns= array(
    '#http://(www\.)?domain-1.com/.*#i',
    '#http://(www\.)?domain-2.com/.*#i',
    ...
);

我有一个包含多个文本和网址的长字符串我想匹配字符串中出现的第一个网址,我只试过这个:

foreach ($patterns as $pattern) {
    preg_match($pattern, $the_string, $match);
    echo '<pre>'; print_r($match); echo '</pre>';
}

它返回空数组,其中某些模式和包含url的数组不匹配,但取决于数组的顺序$patterns

如何找到首先出现的这些模式的匹配。

3 个答案:

答案 0 :(得分:5)

你基本上有三个选择:

  1. 匹配general URL pattern,然后根据您获得的模式运行该网址。如果没有匹配,请继续使用常规模式的第二个结果。
  2. 使用PREG_OFFSET_CAPTURE标志运行所有模式,以获得模式匹配的偏移量。找到最低的偏移量,返回结果
  3. 将您的各种图案组合成一个图案。请注意,模式的长度(64K in compiled form
  4. 有限制

    选项2:

    <?php
    
    $text = "hello world http://www.domain-2.com/foo comes before http://www.domain-1.com/bar";
    $patterns= array(
        '#http://(www\.)?domain-1.com/[^\s]*#i',
        '#http://(www\.)?domain-2.com/[^\s]*#i',
    );
    
    $match = null;
    $offset = null;
    foreach ($patterns as $pattern) {
        if (preg_match($pattern, $text, $matches, PREG_OFFSET_CAPTURE)) {
            if ($matches[0][1] < $offset || $offset === null) {
                $offset = $matches[0][1];
                $match = $matches[0][0];
            }
        }
    }
    
    var_dump($match);
    
    请注意,我改变了您的演示模式。我将.*(任何内容)替换为[^\s]*(除了空格之外的所有内容)以防止模式匹配超出预期

答案 1 :(得分:2)

我想你正在寻找这个:

foreach ($patterns as $pattern) {
    if (preg_match($pattern, $the_string, $match)) {
        echo '<pre>'; print_r($match); echo '</pre>';
        break;
    }
}

<强>更新

然后我认为你应该使用偏移量来解决这个问题:

$matches = array();
foreach ($patterns as $pattern) {
    if (preg_match($pattern, $the_string, $match, PREG_OFFSET_CAPTURE)) {
        $matches[$match[0][1]] = $match[0][0];
    }
}
echo reset($matches);

答案 2 :(得分:1)

我无法想到任何方式,除了一次一个地评估所有字符串,并抓住最早的字符串:

$easliestPos = strlen($the_string) + 1;
$earliestMatch = false;

foreach ($patterns as $pattern) { 
    if (preg_match($pattern, $the_string, $match)) { 
        $myMatch = $match[0];
        $myMatchPos = strpos($myMatch, $the_string);
        if ($myMatchPos < $easliestPos ) {
            $easliestPos = $myMatchPos;
            $earliestMatch = $myMatch ;
        }
    }
 }

 if ($earliestMatch ) {
    echo $earliestMatch;
 }