Preg_match match mais ne capture pas

Preg_match match mais ne capture pas - PHP - Programmation

Marsh Posté le 01-04-2020 à 17:41:41    

Bonjour,
 
Je liste des images dans un dossier, cela fonctionne très bien sauf pour une image en .png contrairement à toutes les autres qui sont en .jpg.
 
Donc je scanne tous les fichiers, puis à partir de leur nom j'applique une expression régulière qui élimine tout ce qui n'a pas la bonne extension, ensuite je récupère le nom de l'image sans son extension :
 

Code :
  1. function constr_ext($value) { //ajout du point devant le nom de l'extension
  2. return '\.' . $value;
  3. }
  4. $extensions = ['jpg', 'jpeg', 'png', 'gif']; //extensions recherchées
  5. $pattern = '/^(.+)' . implode('|', array_map('constr_ext', $extensions)) . '$/'; //expression régulière prenant en compte toutes les extensions souhaitées
  6. $files = scandir($dir1); //liste les fichiers dans le dossier
  7. foreach($files as $key => $value) {
  8. $test = preg_match($pattern, $value, $matches); //vérifie si le nom du fichier (avec extension) respecte l'expression régulière (nom de fichier se terminant par une des extensions listées)
  9. if($key == 275) { //test spécifique au fichier problématique
  10.  echo $matches[0];
  11. }
  12. if($test != 1) { //si ne respecte pas l'expression régulière on désindexe le fichier
  13.  unset($files[$key]);
  14. } else { //sinon on récupère son nom sans l'extension
  15.  $files[$key] = $matches[1];
  16. }
  17. }


 
J'ai inséré un test pour le fichier en question, $matches[0] me renvoie bien ".png" mais $matches[1] me renvoie NULL et $value vaut "256426.png".
 
Je ne capte pas, il détecte bien que dans le nom du fichier il y a l'extension mais ne veut pas capturer.
Le $pattern littéral obtenu est :

Code :
  1. /^(.+)\.jpg|\.jpeg|\.png|\.gif$/


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Marsh Posté le 01-04-2020 à 17:41:41   

Reply

Marsh Posté le 01-04-2020 à 17:43:52    

Désolé, c'est déjà réglé, j'y ai vu plus clair en écrivant mon message, faut utiliser le pattern :

 
Code :
  1. /^(.+)(?:\.jpg|\.jpeg|\.png|\.gif)$/


Message édité par MaybeEijOrNot le 01-04-2020 à 17:58:17

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Marsh Posté le 02-04-2020 à 22:06:30    

Désolé mais ton code me semble bien compliqué :/
 
Avec le bout de code suivant, ça retourne tous les fichiers avec tes extensions voulues :


$files = preg_grep('/\.(jpeg|jpg|png|gif)$/', scandir($dir1));
 
$filesWithoutExtension = array_map(function($file) {
    return basename($file, '.' . pathinfo($file, PATHINFO_EXTENSION));
}, $files);
 
var_dump($filesWithoutExtension);


 
C'est mieux pour toi ?


Message édité par Surfoo le 02-04-2020 à 22:07:08
Reply

Marsh Posté le 03-04-2020 à 00:19:07    

Euh je ne vois pas ce qu'il a de compliqué, il liste les fichiers d'un dossier puis élimine à l'aide d'une expression régulière ceux qui ne répondent pas au critère des extensions recherchées. C'est juste une boucle avec if dedans.

 

L'avantage de mon code, ce qui quitte à utiliser une expression régulière, autant aller jusqu'au bout en utilisant son résultat.

 

Ce qui peut paraître complexe c'est la création du regex mais c'est parce que je veux partir d'un tableau.

 

Au final, ton code est plus "court" (tu écris moins de lignes mais ne fait pas moins d'opérations) mais est probablement moins performant (tu boucles deux fois sur ta liste de fichiers dont un array_map qui applique deux fonctions) et tu ne gagnes pas vraiment en lisibilité.


Message édité par MaybeEijOrNot le 03-04-2020 à 00:20:13

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Marsh Posté le 03-04-2020 à 15:24:45    


Il fait exactement la même chose :

Code :
  1. preg_grep('/\.(jpeg|jpg|png|gif)$/', scandir($dir1))


Ce n'est pas de la magie, ça fait juste répéter un preg_match sur chaque itération du tableau passé en paramètre. :pt1cable:  
 
Comme je le disais, j'utilise une boucle de taille n lorsque lui utilise deux boucles de taille n, le calcul est vite fait !
 
On est d'accord que le regex en dur est plus clair mais ne répond pas à la problématique (que j'ai partiellement exposé) qui fait que le regex n'est pas connu à l'avance.
 
 
EDIT : j'ai simplifié la construction du regex (plus de map) :

Code :
  1. $pattern = '/^.+(?:\.' . implode('|\.',$extensions) . ')$/';


Message édité par MaybeEijOrNot le 03-04-2020 à 15:29:29

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Marsh Posté le 03-04-2020 à 23:13:41    

Plus ou moins, en fait il fait une boucle de taille n puis une boucle plus courte (plus courte des fichiers éliminés). Là où encore une fois je ne fais qu'une boucle de taille n. [:transparency]  
Et même côté mémoire, il instancie un tableau de la taille du nombre de fichiers (comme moi avec scandir), puis instancie un second tableau avec le preg_grep, là où je reste avec un seul tableau.
Alors même si on n'est pas dans le besoin de l'extrême performance, je suis sur 500-1000 fichiers, c'est loin d'être critique mais pas non plus suffisamment anecdotique pour choisir une légère meilleure lisibilité ? [:cond]


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Marsh Posté le 03-04-2020 à 23:34:31    

Par contre je viens de me rendre compte qu'il y avait mésentente, il me retourne la liste des fichiers sans leur extension, moi je veux garder l'extension du fichier, je veux juste éliminer ceux qui n'ont pas l'extension voulue.
Du coup son code se simplifie à :

Code :
  1. $files = preg_grep($pattern, scandir($dir1));


 
Et là je dis oui ! Même si après quelques tests de performance, la différence avec mon code est minime, on est plus rapide de 0,05 - 0,1 ms maintenant. :)


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed