简单的preg_match与捕获组,我错了吗?

时间:2013-08-31 09:07:25

标签: php regex pcre

文件名:

forms.it.yml
validators.en.xliff

我需要提取三个部分(来自文件名):<domain>.<locale>.<format>,所以我最终得到了这个正则表达式:

/^(?P<domain>\.+).(?P<locale>\w{2,}).(?P<format>\w+)$/

但当然它不起作用。应该有一些我不知道的东西。

$match = '/^(?P<domain>\.+).(?P<locale>\w{2,}).(?P<format>\w+)$/';
$subject = 'forms.it.yml';

var_dump(preg_match($match, $subject)); // 0

2 个答案:

答案 0 :(得分:1)

点在你的模式中很特别。通过放入方括号或通过削减它使其变得不寻常。所以点是逐字点。

正如你已经使用第一个点那样做了,你也需要改变它,但是我建议你把它从模式中排除以匹配否则 - 如果贪婪 - 这可能效果不好。而且默认情况下它常常是贪婪的。

/^(?P<domain>[^.]+)\.(?P<locale>[a-zA-Z]{2,})\.(?P<format>\w+)$/
             ##### ^^           ########     ^^
               ^   dot              ^        dot
               |                    |
            not dot      just a little variation

实施例/ Demo

<?php
/**
 * @link http://stackoverflow.com/a/18546468/367456
 */

$match = '/^(?P<domain>[^.]+)\\.(?P<locale>[a-zA-Z]{2,})\\.(?P<format>\\w+)$/';
$subject = 'forms.it.yml';

var_dump(preg_match($match, $subject)); // int(1)

节目输出:

int(1)

使用Possessive Quantifiers

可以进一步优化
/^(?P<domain>[^.]++)\.(?P<locale>[a-zA-Z]{2,}+)\.(?P<format>\w++)$/
                  ^                          ^                 ^

答案 1 :(得分:0)

你好像逃脱了第一个点而不是中间点。

您的第一个小组(domain)与\.+匹配,贪婪地匹配一个或多个文字点。

中间模式.是正则表达式点,因此匹配所有内容。

您希望使用否定的字符类将转义的点更改为点阵图案。我还建议你利用占有量词来加速失败的非匹配文本:

^(?P<domain>[^.]++)\.(?P<locale>[^.]{2,}+)\.(?P<format>.*+)$