IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

preg_match_all : exclusion d'une sous chaine [RegEx]


Sujet :

Langage PHP

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 5
    Points : 2
    Points
    2
    Par défaut preg_match_all : exclusion d'une sous chaine
    Bonjour à tous,

    Je souhaite récupérer les chaînes à traduire dans mon code. Elles se présentent comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    __('texte à traduire');
    __("texte à traduire");
    en employant les motifs suivants j'arrive à quelque chose de correct, mais d'imparfait sur plusieurs points :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $motif1 = "/__\('([^')]+)'\)/";
    $motif2 = "/__\(\"([^\"))]+)\"\)/";
    Actuellement l'exclusion [^')] concerne l'un ou l'autre des caractères alors que je souhaiterais qu'il concerne les deux associés et dans cet ordre là.

    concrètement je voudrais pouvoir récupérer une chaine du type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    __('texte à traduire contenant des (parenthèses) et des \'quotes\'');
    Et pour l'instant ce n'est pas le cas puisque la parenthèse fermante et le quote sont exclus.

    J'ai un doute sur la clarté de mes explications, mais si une âme éclairée pouvait partager un peu de sa lumière je lui en serais reconnaissant

  2. #2
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2004
    Messages : 108
    Points : 175
    Points
    175
    Par défaut
    Bonjour,

    Je pense qu'avec ce pattern $motif1 = "#__\(['"](.*)['"]\)#", vous obtiendrez ce que vous voulez .

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    Merci pour cette réponse,

    J'ai déjà testé ce motif et le problème rencontré était le suivant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    __('première chaîne'); __('deuxième chaîne sur la même ligne');
    $pattern = "/__\(['"](.*)['"]\)/";
    avec comme résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    première chaîne'); __('deuxième chaîne sur la même ligne
    Il faut donc exclure la 'balise' fermante de la chaîne, soit : ') ou ")

    Me suis-je égaré ou y a-t-il du vrai dans ce que je dis ?

  4. #4
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2004
    Messages : 108
    Points : 175
    Points
    175
    Par défaut
    Alors en effet il manque un petit truc pour que cela fonctionne correctement.
    De base le moteur est un bon vivant , je veux dire par la qu'il va manger le maximum tant que cela correspond au pattern indiqué.
    Pour lui demandé de l'être un peu moins il faut utiliser le flag U .
    il s’arrêtera alors dès que le pattern pourra être validé et le reste sera analysé pour un deuxième résultat.

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    Merci pour cette nouvelle intervention

    Hélas il me semble que cette solution n'est pas satisfaisante. Pour reprendre l'exemple précédent :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    __('première chaîne'); __('deuxième chaîne sur la même ligne');
    $pattern = "/__\(['"](.*)['"]\)/U";
    donnera 'p', ce qui est effectivement le moins 'gourmand' des résultats, mais ce n'est pas vraiment ce que je recherche. Maintenant une subtilité m'échappe peut être ?!

  6. #6
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2004
    Messages : 108
    Points : 175
    Points
    175
    Par défaut
    Hmmm non 'p' n'est pas le moins gourmand des résultats. Moins gourmants ne veux pas dire qu'il ne répond pas au pattern. Or 'p' ne répond pas au pattern puisque certe 'p' est précédé par une quote mais non suivie par une quote ou une double quote.

    Je pense que tu as du mal réécrire la regex. N'oublie pas les anti-slash pour les doubles quotes à l'intérieur du pattern .
    $pattern = "/__\(['\"](.*)['\"]\)/U";Mon code de test complet est :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    $a = "__('première chaîne'); __('deuxième chaîne sur la même ligne');";
    preg_match_all('#__\([\'"](.*)[\'"]\)#U',$a,$matches);
    print_r($matches);

    Chez moi le print me retourne :
    Array
    (
    [0] => Array
    (
    [0] => __('première chaîne')
    [1] => __('deuxième chaîne sur la même ligne')
    )

    [1] => Array
    (
    [0] => première chaîne
    [1] => deuxième chaîne sur la même ligne
    )

    )

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    oh oh,

    En effet tu penses bien

    J'avais laissé un petit détail qui changeait tout :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $motif = '/__\([\'"](.)+[\'"]\)/U';
    Au lieu de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $motif = '/__\([\'"](.+)[\'"]\)/U';
    Merci pour ta patience.

    Maintenant pour que tout soit parfait il faudrait que ceci fonctionne aussi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    __('le test (\'quasi\') ultime')
    __("le test (\"quasi\") ultime")
    __('le test ("quasi") ultime')
    __("le test ('quasi') ultime")
    J'ai une vague idée d'utilisation d'assertion avec 2 patterns... mais pas mieux. Et j'ai bien dit vague

    Edit : Ceci semble marcher

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $motif1 = "/__\('(.+)(?<!\\\)'\)/U";
    $motif2 = "/__\(\"(.+)(?<!\\\)\"\)/U";
    Ca me semble délicat en un seul pattern non ?

  8. #8
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2004
    Messages : 108
    Points : 175
    Points
    175
    Par défaut
    Alors il y a possibilité de faire cela avec un seul pattern .
    Voici
    #__\((['"])(.*[^\\])\1\)#
    Directement dans preg_match cela donne preg_match_all('#__\(([\'"])(.*[^\\\])\1\)#U',$a,$matches);.

    Pour la petite explication, je récupère le caractère qui commence la chaine dans un groupe. Et j'utilise ce groupe pour fermer la chaine \1. Après je pars du principe que ce caractère ne ferme que si il n'y a pas d'antislash qui le précède d'où le [^\\\]

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    J'avoue être séduit pas la beauté de la chose

    Et bien non seulement tu auras réussi à résoudre mon problème, mais en plus tu m'auras également appris des choses plus qu'intéressantes sur le fonctionnement de la bête.

    Alors Merci d'avoir passé du temps à m'instruire sur le sujet !

  10. #10
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Juin 2004
    Messages : 108
    Points : 175
    Points
    175
    Par défaut
    Ce fut un plaisir .
    Les regex sont surpuissant si on connait bien toute les facettes de la bêtes.

    Tient en prime, si tu ne connais pas, un petit site pas mal : Regular Expressions. Je le trouve assez bien fait sur les possibilités qu'offre le système .

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [RegEx] extraction d'une sous chaine
    Par zulkifli dans le forum Langage
    Réponses: 2
    Dernier message: 24/03/2006, 13h27
  2. Recherche une sous-chaine dans un champ ?
    Par nerick dans le forum Requêtes
    Réponses: 3
    Dernier message: 06/03/2006, 13h46
  3. je cherche une sous chaine dans une chaine
    Par avprive dans le forum C++
    Réponses: 3
    Dernier message: 17/03/2005, 01h48
  4. Rechercher une sous chaine dans une chaine
    Par annedjomo dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 04/02/2005, 10h36
  5. Rechercher une sous chaine dans une chaine
    Par Oluha dans le forum ASP
    Réponses: 4
    Dernier message: 03/02/2005, 14h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo