preg_match()表现得很奇怪?

时间:2012-01-01 23:18:09

标签: php regex

我想将两个字符串与url进行比较:

$reg1 = "/(^(((www\.))|(?!(www\.)))domain\.com\/paramsindex\/([a-z]+)\/([a-z]+)\/((([a-z0-9]+)(\-[a-z0-9]+){0,})(\/([a-z0-9]+)(\-[a-z0-9]+){0,}){0,})|()\/?$)/";
$reg2 = "/(^(((www\.))|(?!(www\.)))domain\.com\/paramsassoc\/([a-z]+)\/([a-z]+)\/((([a-z0-9]+)(\-[a-z0-9]+){0,})(\/([a-z0-9]+)(\-[a-z0-9]+){0,}){0,})|()\/?$)/";
$uri  = "www.domain.com/paramsindex/cont/meth/par1/par2/par3/";

$r1 = preg_match($reg1, $uri);
echo "<p>First regex returned: {$r1}</p>";

$r2 = preg_match($reg2, $uri);
echo "<p>Second regex returned: {$r2}</p>";

现在这些字符串不一样,区别在于:

www.domain.com/paramsindex/cont/meth/par1/par2/par3/

VS

www.domain.com/paramsassoc/cont/meth/par1/par2/par3/

然而PHP preg_match为它们返回1。 现在你会说这是一个很长的正则表达式,为什么要使用它。事情是我可以建立更短的正则表达式,但它是在飞行中构建的......它你需要像那样。 令我困扰的是,在Rubular正则表达式中它的工作原理应该如此。 在测试它们时我使用的是Rubular,现在我用PHP它不会工作。我知道Rubular是Ruby正则表达式编辑器,但我认为它应该是相同的:(

Rubular测试:here

这里有什么问题?我应该如何在PHP中编写该正则表达式,以便preg_match可以看到差异?正则表达式应该与我已经编写的正则表达式接近,是否有一些简单的解决方案可以解决我的问题?有什么可以忽略的吗?

3 个答案:

答案 0 :(得分:3)

该行为是设计使然,当找到匹配时,preg_match返回1。如果要捕获匹配项,请参阅匹配参数:http://php.net/manual/en/function.preg-match.php

编辑:例如

$matches = array();
$r2 = preg_match($reg2, $uri, $matches);
echo "<p>Second regex returned: ";
print_r($matches);
echo "</p>";

如果没有回答正确的问题,我会留下上述内容来记录我自己的愚蠢。

在正则表达式结束时,您有|()\/?$)/,这将使正则表达式匹配URL以斜杠结尾。把它拿出来,看起来你的测试看起来很金。

答案 1 :(得分:2)

始终记得将操作数分组!

我可以假设这个很难被发现,但这都是因为你使用了or-operator |。您没有正确地对操作数进行分组,因此您的帖子中描述的结果是收益。

您在提供的案例中使用|()将匹配运营商|左侧的完整正则表达式。

要解决此问题,您需要在应该进行OR运算的操作数周围加上括号。


查看一切出错的简单方法是在以下代码段中运行:

$reg1 = "/(^(((www\.))|(?!(www\.)))domain\.com\/paramsindex\/([a-z]+)\/([a-z]+)\/((([a-z0-9]+)(\-[a-z0-9]+){0,})(\/([a-z0-9]+)(\-[a-z0-9]+){0,}){0,})|()\/?$
$reg2 = "/(^(((www\.))|(?!(www\.)))domain\.com\/paramsassoc\/([a-z]+)\/([a-z]+)\/((([a-z0-9]+)(\-[a-z0-9]+){0,})(\/([a-z0-9]+)(\-[a-z0-9]+){0,}){0,})|()\/?$
$uri  = "www.domain.com/paramsindex/cont/meth/par1/par2/par3/";

var_dump (preg_match($reg1, $uri, $match1));
var_dump (preg_match($reg2, $uri, $match2));

print_r ($match1);
print_r ($match2);

输出

int(1)
int(1)
Array
(
    [0] => www.domain.com/paramsindex/cont/meth/par1/par2/par3
    [1] => www.domain.com/paramsindex/cont/meth/par1/par2/par3
    [2] => www.
    [3] => www.
    [4] => www.
    [5] => 
    [6] => cont
    [7] => meth
    [8] => par1/par2/par3
    [9] => par1
    [10] => par1
    [11] => 
    [12] => /par3
    [13] => par3
)
Array
(
    [0] => /
    [1] => /
    [2] => 
    [3] => 
    [4] => 
    [5] => 
    [6] => 
    [7] => 
    [8] => 
    [9] => 
    [10] => 
    [11] => 
    [12] => 
    [13] => 
    [14] => 
    [15] => 
)

如您所见$reg2匹配$uri中的一堆空字符串,这表明我之前所描述的内容。


如果你想出一个关于你想要做什么的简短描述,我可以为你提供一个功能齐全的(并且可能比你现在更整洁)正则表达式。

答案 2 :(得分:1)

您的RegEx很乱,如果您希望它能够工作,您将 更改它。

查看您的paramsindexhttp://www.rubular.com/r/3ptjQ5aIrD

的Rubular

现在,对于paramsassochttp://www.rubular.com/r/o7GCbCsHyX

他们两者都会返回结果。当然它是一个充满空字符串的数组,但 仍然是一个结果。

是两者都为真的原因。

相关问题