我有一系列模式:
$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
,
如何找到首先出现的这些模式的匹配。
答案 0 :(得分:5)
你基本上有三个选择:
PREG_OFFSET_CAPTURE
标志运行所有模式,以获得模式匹配的偏移量。找到最低的偏移量,返回结果选项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;
}