4

Группировать в регулярном выражении можно вложенно

<?php
$regexp = '@^/(tn(-crop)?)/(\d+)x(\d+)/(.+(jpg|png|gif))$@i';
foreach(array('/tn-crop/100x100/foo.jpg', '/tn/100x100/foo.jpg') as $v){
        echo $v.' - '.(preg_match($regexp, $v, $m) ? 'true' : 'false')."\n";
        print_r($m);
}
/tn-crop/100x100/foo.jpg - true
Array
(
    [0] => /tn-crop/100x100/foo.jpg
    [1] => tn-crop
    [2] => -crop
    [3] => 100
    [4] => 100
    [5] => foo.jpg
    [6] => jpg
)
/tn/100x100/foo.jpg - true
Array
(
    [0] => /tn/100x100/foo.jpg
    [1] => tn
    [2] => 
    [3] => 100
    [4] => 100
    [5] => foo.jpg
    [6] => jpg
)