php中的正则表达式:采用最短匹配

时间:2011-02-22 14:15:21

标签: php regex

我正在尝试使用PHP正则表达式但我无法找到正确的方法......

想象一下,我有这个字符串:“你好,我的{{名字是彼得}}和{{我想吃巧克力}}”

我想拍摄{{和}}

之间的部分

但是如果我使用preg_match("/\{\{(.*)?\}\}/", $string)

它返回我一个字符串“{{name is Peter}}和{{我想吃巧克力}}”

我怎么能说出}}的第一个巧合?

谢谢

5 个答案:

答案 0 :(得分:26)

使用

"/{{(.*?)}}/"

表达式".*"贪婪,占用尽可能多的字符。 如果使用".*?",则尽可能使用小字符,即在第一组右括号处停止。

答案 1 :(得分:7)

默认情况下,PCRE功能贪婪。这意味着,引擎总是试图匹配尽可能多的字符。解决方案很简单:告诉他使用U修饰符

进行非贪婪行为
/{{(.+)}}/U

http://php.net/reference.pcre.pattern.modifiers

答案 2 :(得分:2)

你想要“不合适的匹配”:preg_match("/{{(.*?)?}}/", $string)

注意第一个问号 - 默认情况下,正则表达式是“贪婪的”:给定多种匹配方式,它匹配尽可能多的文本。添加问号将使其不合适,因此如果有多种匹配方式,它将匹配尽可能少的字符。

答案 3 :(得分:0)

已编辑

由于非贪婪的匹配似乎比否定的(see here)更快,我也改变了我的答案。以为这是另一回事......

preg_match("/\{\{(.*?)\}\}/", $string)

您可能希望使用preg_match_all来获取所有匹配

答案 4 :(得分:0)

这对我有用。

$subject = 'Hello {{name}}, here is an email {{email}} and phone # {{phone}}';
$replace = array(
    '{{name}}' => 'Bob',
    '{{email}}' => 'email@me.com',
    '{{phone}}' => '5155554455'
);

$output = preg_replace_callback('{{{?(#[a-z]+ )?[a-z]+.[a-z]*}?}}', function($match) use ($replace) {
    if(isset($replace[$match[0]])){
        return ($replace[$match[0]]);
    } else {
        return($match[0]);
    } 
}, $subject);

var_dump($output);