Why does this regex match too much? (Doesn't s

2020-04-19 06:01发布

This code outputs the $captured array, but $captured[1] contains bar/this rather than my expected bar. What's missing in my regex to stop from returning more than 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>';

标签: php regex
3条回答
对你真心纯属浪费
2楼-- · 2020-04-19 06:35

The dot is greedy and matches as many characters as possible. Either make it lazy:

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

or keep it from matching slashes:

$pattern = str_replace(':any', '([^\/]+)', $pattern);
查看更多
成全新的幸福
3楼-- · 2020-04-19 06:36

Use a non-greedy modifier to make the + match as few characters as possible instead of as many as possible:

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

You probably also want to add delimiters round your regular expression and anchor it to the start of the string:

$pattern = '#^/foo/:any/#';
查看更多
趁早两清
4楼-- · 2020-04-19 06:36

Your code is rather confusing and misleading and if run it, it outputs a warning:

Warning: preg_match(): Unknown modifier '(' in php shell code on line 1

What I think is wrong is:

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

because you need to escape a forward slash in regexp.

After this is fixed the script returns:

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

Which is an expected result. As you match foo/ and everything afterwards with (.*). If you want to match anything until the next forward slash you have some possibilities:

$pattern = '/foo/(.*?)/'     #non greedy
$pattern = '/foo/([^\/]*)/'  #not matching any forward slash
$pattern = '@foo/:any/@'     #or using different start and end markers, e.g. @
查看更多
登录 后发表回答