Search code examples
phpregexfilepreg-match

Fastest way to check file extension in list using preg_match


I have a list of file extensions that must be check it's existence to any file (name + extension).

I want to use preg_match function, so I need an appropriate regex pattern with fastest logic and could produce shortest matches array (array length = 1).

File extensions = jpg|jpeg|png|gif|pdf

Example:

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

Correct file (name + extension) Input:

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

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

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

Output:

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

Incorrect file (name + extension) Input:

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

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

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

Output:

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


Solution

  • The following regular expression matches a whole line .* if it ends in a period \. followed by one of the given file extensions (?:jpe?g|png|gif|pdf), while accounting for an optional group of query parameters (?:\?\S+)? preceding the end of the line $:

    /.*\.(?:jpe?g|png|gif|pdf)(?:\?\S+)?$/i
    

    See regex demo. The i flag enables case-insensitive matching.

    In PHP:

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

    Which leads to 1 (meaning success) as $result and an array containing the matched line as $matches.

    In case you want to deal with a list of texts and only grab the ones matching the pattern, you could also use preg_grep():

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

    $results then contains:

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