Lorsqu'une regex est utilisée pour récupérer des morceaux de chaîne, il est intéressant d'obtenir un tableau associatif plutôt qu'un tableau indexé.

Cela peut être fait avec :
<?php
preg_match_all ("#^$project \((?P<version>[0-9-.]+)-\d+\) (?P<state>\w+); .+$".
                "(?P<changes>.+)".
                "^ -- (?P<maintainerName>.+) <(?<maintainerMail>.+)>  ".
                "(?P<published>.+)$".
                "#smU"$changelog$matches);
// Ne récupère que les entrées définies de manière associatives, sans le tableau caché, et
// en supprimant les données vides
$matches array_filter($matches"is_string"ARRAY_FILTER_USE_KEY);
$matches array_map("current"$matches);
$matches array_filter($matches);

print_r ($matches);

On obtient ainsi un tableau contenant les indexes "version", "state", "changes"...

Voir http://fr2.php.net/manual/en/function.preg-match-all.php#example-5380