使用 preg_match 检查列表中文件扩展名的最快方法

Fastest way to check file extension in list using preg_match

我有一个文件扩展名列表,必须检查它是否存在于任何文件(名称 + 扩展名)。

我想使用 preg_match 函数,所以我需要一个具有最快逻辑并且可以生成最短匹配数组(数组长度 = 1)的适当正则表达式模式。

文件扩展名 = jpg|jpeg|png|gif|pdf

示例:

$pattern = ????;
$matches = '';
$result = preg_match($pattern, $filename, $matches);

正确的文件(名称+扩展名)输入:

1) $filename = 'trial.gen.OO7.jpg';

2) $filename = 'http://localhost/index.php/profile/Whosebug/0000000123.911.png?_id=900d';

3) $filename = 'fast-n-furious.pdf';

输出:

=> $result: true
=> $matches:
    1) array( [0] => trial.gen.OO7.jpg )
    2) array( [0] => http://localhost/index.php/profile/Whosebug/0000000123.911.png )
    3) array( [0] => fast-n-furious.pdf )

不正确的文件(名称+扩展名)输入:

1) $filename = 'trial.gen.OO7.jpg.php';

2) $filename = 'http://localhost/index.php/profile/Whosebug/0000000123.911.?_id=84d';

3) $filename = 'fast-n-furious';

输出:

=> $result: false
=> $matches: array( [] )

以下正则表达式匹配整行 .*,如果它以句点 \. 结尾,后跟一个给定的文件扩展名 (?:jpe?g|png|gif|pdf),同时考虑一组可选的行尾 $:

之前的查询参数 (?:\?\S+)?
/.*\.(?:jpe?g|png|gif|pdf)(?:\?\S+)?$/i

参见 regex demoi 标志启用不区分大小写的匹配。

在PHP中:

$filename = 'http://localhost/index.php/profile/Whosebug/0000000123.911.png?_id=900d';
$pattern = '/.*\.(?:jpe?g|png|gif|pdf)(?:\?\S+)?$/i';
$result = preg_match($pattern, $filename, $matches);

这导致 1 (meaning success) 作为 $result 和包含匹配行的数组 $matches.

如果你想处理一个文本列表并且只抓取与模式匹配的文本,你也可以使用 preg_grep():

$texts = [
    'trial.gen.OO7.jpg', 
    'http://localhost/index.php/profile/Whosebug/0000000123.911.png?_id=900d', 
    'fast-n-furious.pdf', 
    'trial.gen.OO7.jpg.php', 
    'http://localhost/index.php/profile/Whosebug/0000000123.911.?_id=84d', 
    'fast-n-furious'
];
$results = preg_grep($pattern, $texts);

$results 然后包含:

Array
(
    [0] => trial.gen.OO7.jpg
    [1] => http://localhost/index.php/profile/Whosebug/0000000123.911.png?_id=900d
    [2] => fast-n-furious.pdf
)

经过一番尝试,终于解决了问题。

收件人: @oriberu, @WiktorStribizew, @u_mulder,等等。 : 感谢您的评论和帮助。

这是为任何需要它的人准备的功能。随意复制并粘贴此代码以用于您的软件开发。

/* set isFullPath argument to true for full path match result
    otherwise set to false for file name + extension result (no full path)
 */
function isMatchExtension($extList, $filePath, &$matches, $isFullPath = false) {

    $prefix = $isFullPath ? '.*' : '[^\/|\\]*';

    /* make sure to check for "?" mark to handle file extension redundancy possibility inside the file path
        eg:
          extension files: 001|002|003|004|005|006|007

          for filePath: '/trial/profile.001/files/anyfile.007';

          then match should be: (for full path)
          => Array( [0] => /trial/profile.001/files/anyfile.007 )

          or: (for file name + extension only)
          => Array( [0] => anyfile.007 )
     */
    $pattern = "/$prefix\.(?:$extList)(?=\?)/i";

    /* we add $filePath with "?" mark to make sure the path has it.
    return preg_match($pattern, $filePath.'?', $matches);
}

// Usage Example:

$extList = 'jpg|jpeg|png|gif|pdf|html';

$filePath = 'http://localhost/index.php/profile/Whosebug/0000000123.911.png?_id=900d';

$isFullPath = false;

$matches = [];

$isMatch = isMatchExtension($extList, $filePath, $matches, $isFullPath);

 // display result
 echo 'result: ' . ($isMatch ? 'true' : 'false') . '</br>';
 echo 'matches: </br>';
 print_r($matches);

 // the output:
 result: true
 matches:
 Array( [0] => 0000000123.911.png )