preg_match是两种不同(但有些相似)的字符串模式?

时间:2015-03-25 23:11:21

标签: php regex switch-statement preg-match

我循环遍历PHP文件名数组,以构建匹配两种不同模式的文件选择列表。

我让它在一种或另一种模式上工作,但不能同时工作:

    foreach ($file_array as $file_link) {
    $p = '~(-([a-z]{2})\.pdf(|(-([a-z]{4})\.pdf)~';
    preg_match($p, $file_link, $matches);
    switch ($matches[1]) {
        case 'en':
            $link_array[1] = array('English', $file_link);
            break;
        case 'ja':
            $link_array[2] = array('日本語', $file_link);
            break;
        ...
        case 'ptbr':
            $link_array[13] = array('Português brasileiro', $file_link);
            break;
        case 'ptpt':
            $link_array[14] = array('Português europeu', $file_link);
            break;
        ...
    }
    ...
}

$ file_array中的文件格式为:

  • file-name-en.pdf
  • 文件名-ja.pdf
  • 文件名-ptbr.pdf
  • 文件名-ptpt.pdf

我希望匹配-([a-z]{2})\.pdf-([a-z]{4})\.pdf模式。我在上面的$p = '~(-([a-z]{2})\.pdf(|(-([a-z]{4})\.pdf)~';中遗漏了什么才能使其发挥作用。

此外,还有一种更好的方法可以将文件名更改为另一种格式(我试图避免)吗?

我的客户实际上想要这种格式的文件,但看起来更麻烦:

  • 文件名-PT-br.pdf
  • 文件名-PT-pt.pdf

谢谢!

约翰

2 个答案:

答案 0 :(得分:1)

使用此正则表达式以及将捕获(?:-[a-z]{2})?的非捕获组pt-br形式的其他检查:

 `-([a-z]{2}(?:-[a-z]{2})?|[a-z]{4})\.pdf`

 $p = "~-([a-z]{2}(?:-[a-z]{2})?|[a-z]{4})\.pdf~";

查看demo

答案 1 :(得分:1)

如果您想在单个正则表达式中执行此操作,请尝试以下内容(请原谅%边界字符,与~不同。x修饰符用于允许评论

$regex = '%
-                            # starting -
(                            # start grouping parenthesis 
    [a-z]{2}                 #     a through z repeated twice
    |                        #     or
    [a-z]{4}                 #     a through z repeated four times
)                            # end group
\.pdf$                       # string ends in .pdf
%x';

此外,虽然正则表达总是一个有趣的练习,但不要害怕为每个模式使用单个正则表达式。虽然理论上的性能受到了影响,但它很可能不会影响您的应用程序。同样,不要害怕避免使用正则表达式进行更简单的爆炸/内爆

$parts      = explode('.', $filename);
$extension  = array_pop($parts);
$full       = implode('',  $parts);  
$parts      = explode('-', $full);

$identifier = array_pop($parts);

switch($identifier)
{
    case 'en':
        break;
    //etc...
}