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

Php preg_match显示foreach循环中的第一个匹配,php,regex,preg-match,Php,Regex,Preg Match,我有一系列的模式: $patterns= array( '#http://(www\.)?domain-1.com/.*#i', '#http://(www\.)?domain-2.com/.*#i', ... ); 我有一个包含多个文本和url的长字符串,我想匹配字符串中出现的第一个url,我只尝试了以下方法: foreach ($patterns as $pattern) { preg_match($pattern, $the_string, $match)

我有一系列的模式:

$patterns= array(
    '#http://(www\.)?domain-1.com/.*#i',
    '#http://(www\.)?domain-2.com/.*#i',
    ...
);
我有一个包含多个文本和url的长字符串,我想匹配字符串中出现的第一个url,我只尝试了以下方法:

foreach ($patterns as $pattern) {
    preg_match($pattern, $the_string, $match);
    echo '<pre>'; print_r($match); echo '</pre>';
}
foreach($patterns作为$pattern){
preg_match($pattern,$the_string,$match);
回显“”;打印($match);回显“”;
<?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);
}
它返回空数组,其中某些模式与包含url的数组不匹配,但这取决于数组的顺序
$patterns


我怎样才能找到这些最先出现的模式中的任何匹配项。

我猜您正在寻找以下内容:

$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);

您基本上有三种选择:

  • 匹配一个URL,然后根据已有的模式运行该URL。如果没有匹配的结果,则继续使用常规模式的第二个结果
  • 使用
    PREG\u OFFSET\u CAPTURE
    标志运行所有模式,以获得模式匹配的偏移量。找到最小偏移量,返回结果
  • 将您的各种模式组合为一种模式。请注意,图案的长度是有限制的()

  • 备选案文2:


    除了一次评估所有字符串,并获取最早的字符串外,我想不出任何方法:

    $easliestPos=strlen(_字符串)+1;
    $earliestMatch=false;
    foreach($patterns作为$pattern){
    如果(preg_match($pattern,$the_string,$match)){
    $myMatch=$match[0];
    $myMatchPos=strpos($myMatch,$u字符串);
    如果($myMatchPos<$easliestPos){
    $easliestPos=$myMatchPos;
    $earliestMatch=$myMatch;
    }
    }
    }
    如果($earliestMatch){
    echo$earliestMatch;
    }
    
    您能给我们展示一个您试图匹配的URL示例和一个示例模式吗?问题可能在于你的正则表达式模式,而不是你的PHP。你键入它的速度比我快:)我不想在第一次匹配后停止,这将返回一个匹配,即使它位于字符串的末尾,但它的模式位于数组模式的开头。虽然这是一个可行的解决方案,但是
    ksort()
    是对性能的不必要浪费…@rodneyrehm感谢您删除了它。我还是喜欢你的:)
    <?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);
    
    $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;
     }