为什么这个正则表达式匹配得太多了? (不要停在斜线上)

时间:2011-11-11 22:28:49

标签: php regex

此代码输出$captured数组,但$captured[1]包含bar/this而非预期的bar。我的正则表达式中缺少什么来阻止返回超过bar

<?php

    $pattern = '/foo/:any/';
    $subject = '/foo/bar/this/that';

    $pattern = str_replace(':any', '(.+)', $pattern);
    $pattern = str_replace(':num', '([0-9]+)', $pattern);
    $pattern = str_replace(':alpha', '([A-Za-z]+)', $pattern);

    echo '<pre>';

    $pattern = '#^' . $pattern . '#';
    preg_match($pattern, $subject, $captured);

    print_r($captured);
    echo '</pre>';

3 个答案:

答案 0 :(得分:5)

使用non-greedy modifier+匹配为少数字符,而不是许多

$pattern = str_replace(':any', '(.+?)', $pattern);
                                   ^

您可能还想在正则表达式中添加delimiters并将其锚定到字符串的开头:

$pattern = '#^/foo/:any/#';

答案 1 :(得分:1)

点贪婪,尽可能多地匹配字符。让它变得懒惰:

$pattern = str_replace(':any', '(.+?)', $pattern);

或防止匹配斜杠:

$pattern = str_replace(':any', '([^\/]+)', $pattern);

答案 2 :(得分:0)

您的代码相当混乱和误导,如果运行它,它会输出一个警告:

  

警告:preg_match():未知的修饰符&#39;(&#39;在第1行的php shell代码中

我认为错误的是:

$pattern = '/foo/:any/';
#should be
$pattern = '/foo\/:any/';

因为你需要在正则表达式中转义正斜杠。

修复此问题后,脚本将返回:

(
  [0] => foo/bar/this/that
  [1] => bar/this/that
)

这是预期的结果。当您将foo/和之后的所有内容与(.*)匹配时。如果你想匹配任何东西,直到下一个正斜杠你有一些可能性:

$pattern = '/foo/(.*?)/'     #non greedy
$pattern = '/foo/([^\/]*)/'  #not matching any forward slash
$pattern = '@foo/:any/@'     #or using different start and end markers, e.g. @