296 votes

Comment faire correspondre, mais pas capturer, une partie d'une expression rationnelle ?

J'ai une liste de chaînes. Certaines d'entre elles sont de la forme 123-...456 . La partie variable "..." peut être :

  • la chaîne "apple" suivie d'un trait d'union, par exemple 123-apple-456
  • la chaîne "banane" suivie d'un trait d'union, par exemple 123-banana-456
  • une chaîne vide, par exemple 123-456 (noter qu'il n'y a qu'un seul trait d'union)

Tout mot autre que "pomme" ou "banane" est invalide.

Dans ces trois cas, j'aimerais faire correspondre "apple", "banana" et "", respectivement. Notez que je ne veux jamais capturer le trait d'union, mais je veux toujours correspondre il. Si la chaîne n'est pas de la forme 123-...456 comme décrit ci-dessus, il n'y a pas de correspondance du tout.

Comment écrire une expression régulière pour faire cela ? Supposons que j'ai une saveur qui autorise les groupes lookahead, lookbehind, lookaround et non-capturing.


L'observation clé ici est que lorsque vous avez une "pomme" ou une "banane", vous avez doit également ont le trait d'union de fin, mais vous ne voulez pas le faire correspondre. Et lorsque vous faites correspondre la chaîne vide, vous ne doit pas ont un trait d'union à la fin. Une regex qui encapsule cette assertion sera la bonne, je pense.

0 votes

Vous voulez que tout corresponde, sauf les traits d'union ?

0 votes

J'ai un exemple beaucoup plus simple, j'ai me@company.org et je veux faire correspondre la société afin de la remettre pour un traitement ultérieur.

437voto

Gumbo Points 279147

La seule façon de ne pas capturer quelque chose est d'utiliser assertions de contournement :

(?<=123-)((apple|banana)(?=-456)|(?=456))

Car même avec les groupes non captifs (?:…) l'expression régulière entière capture leur contenu. Mais cette expression régulière ne correspond qu'à apple o banana s'il est précédé de 123- et suivi par -456 ou correspond à la chaîne vide si elle est précédée de 123- et suivi par 456 .

Tour d'horizon

Nom

Ce qu'il fait

(?=foo)

Aperçu de la situation

Affirme que ce qui suit immédiatement la position actuelle dans la chaîne est foo

(?<=foo)

Regarder derrière soi

Affirme que ce qui PRÉCÈDE immédiatement la position actuelle dans la chaîne est foo

(?!foo)

Aperçu négatif

Affirme que ce qui suit immédiatement la position actuelle dans la chaîne de caractères n'est PAS foo

(?<!foo)

Regard négatif

Affirme que ce qui précède immédiatement la position actuelle dans la chaîne de caractères n'est PAS foo

1 votes

+1 - Dans ce cas, vous pouvez contourner le problème en utilisant le groupe 1 plutôt que le groupe 0, mais il s'agit d'une excellente (et subtile !) distinction.

0 votes

@Ben Blank : Tout dépend de la façon dont on interprète les termes "match" et "capture".

12 votes

Non pris en charge par JavaScript, yay ! ce serait bien d'avoir une méthode adaptée aux JS, mais ce n'est pas mal du tout, +0.5 (en arrondissant ;D )

17voto

op1ekun Points 1236

En javascript, essayez : /123-(apple(?=-)|banana(?=-)|(?!-))-?456/

Rappelez-vous que le résultat se trouve dans le groupe 1

Démonstration de Debuggex


Sur la base des informations fournies par Germán Rodríguez Herrera

8voto

Thomas Points 2295

Essayez :

123-(?:(apple|banana|)-|)456

Cela correspondra à apple , banana ou une chaîne vide, suivie d'un 0 ou d'un 1 trait d'union. J'avais tort de ne pas avoir besoin d'un groupe de capture. Je suis bête.

1 votes

Ce n'est pas correct puisqu'il correspond, par exemple, à "123-coconut-456".

1 votes

Je pensais que vous vouliez que ce soit plus général... corrigé.

6voto

J'ai modifié une des réponses (par @op1ekun) :

123-(apple(?=-)|banana(?=-)|(?!-))-?456

La raison est que la réponse de @op1ekun correspond également à "123-apple456" sans le trait d'union après pomme.

4voto

slosd Points 867

Essayez ceci :

/\d{3}-(?:(apple|banana)-)?\d{3}/

1 votes

Ce n'est pas correct puisqu'il correspond, par exemple, à "123-coconut-456".

0 votes

@david : en quoi cela diffère-t-il de votre exemple de la "banane" ?

0 votes

@SilentGhost : Je sólo veulent capturer apple o banana ou "". Toutes les autres valeurs sont invalides, comme je l'ai indiqué.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X