php preg_match返回相同模式的不同匹配数

时间:2010-05-12 07:21:32

标签: php regex preg-match roman-numerals

我正在尝试将preg_match与罗马数字转换为整数转换器。问题是,对于某些输入,preg_replace似乎给出的匹配太少。代码:

function romanNumeralToInt($romanNumeral)
{   preg_match
    (   '/^(M?M?M?)'
        .'((CM)|(CD)|((D?)(C?C?C?)))'
        .'((XC)|(XL)|((L?)(X?X?X?)))'
        .'((IX)|(IV)|((V?)(I?I?I?)))$/', $romanNumeral, $match);
    print_r($match);

    $result=0;
    $result += 1000*strlen($match[1]);
    if(strlen($match[3]) != 0){$result += 900;}
    if(strlen($match[4]) != 0){$result += 400;}
    if(strlen($match[5]) != 0)
    {   $result += 100*strlen($match[7]) + 500*strlen($match[6]);
    }
    if(strlen($match[9]) != 0){$result += 90;}
    if(strlen($match[10]) != 0){$result += 40;}
    if(strlen($match[11]) != 0)
    {   $result += 10*strlen($match[13]) + 50*strlen($match[12]);
    }
    if(strlen($match[15]) != 0){$result += 9;}
    if(strlen($match[16]) != 0){$result += 4;}
    if(strlen($match[17]) != 0)
    {   $result += 1*strlen($match[19]) + 5*strlen($match[18]);
    }

    return $result;
}

echo romanNumeralToInt("XXVIII"); // gives correct results

但任何以“IV”结尾的罗马数字都会截断最后3场比赛($ match只包含0-16而不是0-19的元素),同样任何以“IX”结尾的罗马数字都会被切断在过去的4场比赛中。

这是预期的行为,还是我的PHP错误?

1 个答案:

答案 0 :(得分:1)

我希望这是预期的行为。 =)

正则表达式尝试从左到右匹配OR组,一旦找到匹配就停止,因此如果找到IV或IX,它将永远不会尝试匹配最后三个(或四个)组。

实际上,我认为,如果你的表达式包含CM或XL之类的东西,那么其他一些条目也会丢失。

我发现使用RegExr可以帮助调试正则表达式。将其用于正则表达式,一些组捕获空字符串,而某些组包含NO MATCH。