preg_replace: groupe de capture non trouvé

Mais bien présent avec preg_match_all

a marqué ce sujet comme résolu.

Bonjour à tous !

Je viens vers vous pour tenter de comprendre quelque chose qui vous paraîtra peut-être logique, mais qui m’échappe.

Avec l’idée de "normaliser" des noms de classes sous forme snake_lower_case, j’utilise preg_replace('`(?<=[a-z])([A-Z]+)`', '-$1', $objectName) couplé à strtolower(), ce qui fonctionne très bien quand $objectName ne comprend pas d’espace de nom.

Mais justement, je vais devoir faire le même genre de traitement, mais sur des noms d’objets complets. Du coup, appeland déjà preg_replace() qui permet d’effectuer plusieurs remplacements, je me suis dit que je pouvais bien utiliser une autre regex. Mais apparemment, ça ne fonctionne pas comme ça.

Ma nouvelle regex était simplement '`(?<=\\\\)[A-Za-z]+$`', et je m’attendais à pouvoir récupérer le nom de ma classe avec $0, vu que l’assertion était pour moi non-capturante. Surprise, je récupère l’entier de ma chaîne initiale. Je tente alors avec $1 et là, c’est la partie "complémentaire" de celle que je souhaite que je me vois retourner. Pareil, avec $2 et quelques suivants que je teste pour être sûr.

Je remarque alors que dans ma première regex, j’avais des parenthèses pour le groupe après l’assertion. OK, je teste donc avec '`(?<=\\\\)([A-Za-z]+)$`'. Seulement au lieu d’avoir l’espace de nom dès $1, je l’ai à partir de $2, $0 et $1 me retournant ma chaîne initiale.

Perdu, je tente de voir ce que me retourne preg_match() : avec la première expression, j’ai bien le nom de ma classe, et avec la seconde, je l’ai même deux fois…

Histoire d’en être sûr, je tente de voir ce que valent quelques autres groupes. Avec la première regex, si j’utilise le masque de remplacement $0, $1, $2, $3, $4, j’ai comme résultat la chaîne initiale pour $0, et rien pour les autres. Avec la seconde, surprise ! J’ai aussi ma chaîne complète pour $0, mais je récupère aussi juste le nom de la classe pour $1.
Mais du coup, pourquoi est-ce que l’utilisation de $1 tout seul avec la seconde regex me retournait pourtant ma chaîne initiale ?!

J’ai tenté avec preg_match(), et là pourtant, avec ma première regex j’ai bien mon nom de classe, et avec la seconde je l’ai deux fois, mais plus trace de la chaîne initiale dans les résultats…

Merci d’avance.

+0 -0

Oui, je teste sur ce site avant de passer dans mon code. La première regex me sortait "mon" résultat à l’index 0, la seconde à l’index 1.

Une adaptation de regex que tu me proposes me retourne bien ce que j’attendrais avec regex101, mais dans PHP je n’ai pas le même résultat.
J’ai tenté '`[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]+$`' afin de ne capturer que le nom de la classe. regex101 me semble bien capturer ce que j’attendais, mais en PHP, je me retrouve avec ma chaîne initiale comme résultat…

Tant qu’à faire, j’ai tenté avec PHP 5.6.34, 7.0.28, 7.1.15 et 7.2.3, mêmes résultats.

+0 -0

Ce sont les délimiteurs. Certains mettent #, d’autres @, j’ai eu vu ~, et en JavaScript on aurait littéralement / sans guillemets, moi j’utilise `. Je n’aurais pas dû mettre les ' avec ?

Mon entrée de test est la chaîne Moi\Je\Dis\BienVIvant, et je cherche à récupérer déjà BienVIvant, et au final (en deux passes) bien_vivant. L’idée est donc de récupérer le nom de la classe depuis le FQCN fourni par la "constante magique" __CLASS__ ou toute autre chaîne similaire.
Ma seconde passe est déjà fonctionnelle.

Comme d’habitude, je ne cherche pas uniquement une solution, mais aussi à comprendre ce qu’il y a de faux dans mes solutions.
Parce qu’un tel comportement sur quatre versions de PHP, ce n’est pas un souci du langage, on est d’accord  :)

+0 -0

:waw:  Oui, voilà  :lol:

Dire que je n’ai rien vu d’aussi simple dans ce que j’ai pu trouver par-ci, par-là…


Mais cela n’explique cependant pas mon erreur  ^^

Je vais donc utiliser deux fonctions supplémentaires en attendant.

+0 -0

(Je crois que c’est ton 3e topic en 1 semaine, et la 3e fois que tu cherchais une solution compliquée à un problème simple. C’est un syndrome très classique chez notre espèce, on le sait. Peut-être que tu devrais tenter une approche radicalement différente pour ensuite converger vers une approche plus pragmatique quand t’es face à un problème ? Si t’as l’habitude de commencer par le haut, commence par le bas. Si t’as l’habitude de d’abord chercher la bonne manière puis l’implémenter, cherche d’abord le quick’n’dirty puis tente de le rendre beau/maintenable ? :) )

Je peux pas expliquer pourquoi ta regex marchait pas parce que pour moi elle marche. J’ai pas PHP alors j’utilise une sandbox mais bon : http://sandbox.onlinephpfunctions.com/code/91fa4abcf03c91c3b6da4bbaae6611d7e7840a61

+1 -0

Tu remplaces ce que je recherche par une chaîne statique, moi j’aimerais récupérer ce que tu remplaces… Mais effectivement, plutôt que de tenter de récupérer ce que je veux, je peux remplacer ce que je ne veux pas par rien… Au moins, le vide est statique  :soleil:

+0 -0
+0 -0

Vous avez tous les deux compris ce que je voulais récupérer, et vos solutions sont toutes les deux fonctionnelles et efficaces, merci, vraiment.  :)

Ce que je cherche à comprendre maintenant, c’est ce qui n’est pas correct dans ma regex pour que cela ne fonctionne pas comme je m’y attendais avec un "bête" preg_replace(). Est-ce que c’est une limitation de PCRE, ou juste la manière dont elle est construite, ou la manière dont les remplacements sont effectués ?


A ma relative décharge par rapport à tout ça, ça doit faire environ deux semaines que je ne dors plus trop bien, je pense que ça n’aide pas. Je vais aller me coucher, ça me changera.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte