2017-01-11 6 views
0

Ne peut pas obtenir pourquoi cette regex (regex101)groupe capture répétée PCRE

/[\|]?([a-z0-9A-Z]+)(?:[\(]?[,][\)]?)?[\|]?/g 

capture toutes les entrées, alors que ce (regex101)

/[\|]+([a-z0-9A-Z]+)(?:[\(]?[,][\)]?)?[\|]?/g 

capture seulement |Func

Chaîne d'entrée est |Func(param1, param2, param32, param54, param293, par13am, param)|

Comment puis-je faire correspondre le groupe de capture répétée de manière normale? Par exemple. J'ai regex

/\(\(\s*([a-z\_]+){1}(?:\s+\,\s+(\d+)*)*\s*\)\)/gui 

et chaîne d'entrée est ((string , 1 , 2)). Regex101 dit "un groupe de capture répété capturera seulement la dernière itération Mettez un groupe capturant autour du groupe répété pour capturer toutes les itérations ...". J'ai essayé de suivre ce conseil, mais cela ne m'a pas aidé.

+1

Voir ['\ | + ([a-z0-9A-Z] +) (?: \ (? (\ W + (?: \ S *, \ s * \ w +) *) \)?)? \ |? '] (https://regex101.com/r/ypZGcv/3). Vous ne pouvez pas capturer toutes les captures répétées avec PCRE, vous pouvez les faire correspondre en utilisant une regex '\ G'. Voir ['(?: \ G (?! \ A) \ s *, \ s * | \ | + ([a-z0-9A-Z] +) \() \ K \ w +'] (https://regex101.com/r/ypZGcv/4) –

+0

Je ne savais pas que je ne pouvais pas tout capturer en un seul appel avec PCRE Maintenant, je comprends, c'est pourquoi regex101 me demandait de capturer le groupe répétitif pour l'intégrer Merci beaucoup pour votre aide! – user2890234

Répondre

1

Votre expression regex /[\|]+([a-z0-9A-Z]+)(?:[\(]?[,][\)]?)?[\|]?/g ne correspond pas, car vous n'avez pas défini de motif correspondant aux mots entre parenthèses. Vous pouvez le corriger en tant que \|+([a-z0-9A-Z]+)(?:\(?(\w+(?:\s*,\s*\w+)*)\)?)?\|?, mais toutes les valeurs entre parenthèses correspondent à un seul groupe que vous devrez diviser ultérieurement.

Il n'est pas possible d'obtenir un nombre arbitraire de captures avec une regex PCRE, car en cas de captures répétées, seule la dernière valeur capturée est stockée dans la mémoire tampon du groupe.

Ce que vous pouvez faire est obtenir des correspondances mutliple avec preg_match_all capturant le délimiteur initial.

Donc, pour correspondre à la deuxième chaîne, vous pouvez utiliser

(?:\G(?!\A)\s*,\s*|\|+([a-z0-9A-Z]+)\()\K\w+ 

Voir the regex demo.

Détails:

  • (?:\G(?!\A)\s*,\s*|\|+([a-z0-9A-Z]+)\() - soit la fin de la partie précédente (\G(?!\A)) et une virgule fermée avec 0+ espacements (\s*,\s*), ou | 1+ symboles (\|+), suivie d'une + caractères alphanumériques (capturé dans le Groupe 1, ([a-z0-9A-Z]+)) et un symbole ( (\()
  • \K - omettent le texte correspondant jusqu'à présent
  • \w+ - 1+ mot chars.
+1

J'ai essayé de passer la deuxième regexp comme paramètre de 'preg_match_all' et c'est exactement ce dont j'ai besoin.De plus, la première capture de regexp et d'analyse parentale semble plus claire, mais elle nécessite au moins +1 preg_match, donc je choisirais la deuxième option. Merci pour l'excellente explication! – user2890234

+1

Oui, juste upvoted votre réponse quand a obtenu la notation requise pour cette action :) Il y a quelques heures je n'ai pas assez d'avis pour upvote – user2890234