J’ai une liste de chaînes. Certains d’entre eux sont de la forme 123-...456
. La partie variable “…” peut être:
123-apple-456
123-banana-456
123-456
(notez qu’il n’y a qu’un trait d’union) Tout mot autre que “pomme” ou “banane” est invalide.
Pour ces trois cas, je voudrais faire correspondre “pomme”, “banane” et “”, respectivement. Notez que je ne veux jamais capturer le trait d’union, mais je veux toujours le faire correspondre . Si la chaîne n’a pas la forme 123-...456
comme décrit ci-dessus, alors il n’y a pas de correspondance du tout.
Comment écrire une expression régulière pour le faire? Supposons que je possède une saveur qui permette des groupes d’parsing, de recherche, d’parsing et de capture.
L’observation clé ici est que lorsque vous avez soit “pomme” ou “banane”, vous devez également avoir le trait d’union, mais vous ne voulez pas le faire correspondre. Et lorsque vous correspondez à la chaîne vide, vous ne devez pas avoir le tiret de fin. Une regex qui encapsule cette assertion sera la bonne, je pense.
La seule façon de ne pas capturer quelque chose consiste à utiliser des assertions :
(?<=123-)((apple|banana)(?=-456)|(?=456))
Parce que même avec des groupes non capturés (?:…)
L'expression régulière entière capture leur contenu correspondant. Mais cette expression régulière correspond uniquement à apple
ou à 123-
si elle est précédée de 123-
et suivie de -456
, ou si elle correspond à la chaîne vide si elle est précédée de 123-
et suivie de 456
.
|Lookaround | Name | What it Does | ----------------------------------------------------------------------- |(?=foo) | Lookahead | Asserts that what immediately FOLLOWS the | | | | current position in the ssortingng is foo | ------------------------------------------------------------------------- |(?<=foo) | Lookbehind | Asserts that what immediately PRECEDES the| | | | current position in the string is foo | ------------------------------------------------------------------------- |(?!foo) | Negative | Asserts that what immediately FOLLOWS the | | | Lookahead | current position in the string is NOT foo| ------------------------------------------------------------------------- |(?
Mise à jour: Merci à Germán Rodríguez Herrera!
En javascript essayez: /123-(apple(?=-)|banana(?=-)|(?!-))-?456/
Rappelez-vous que le résultat est dans le groupe 1
Debuggex Demo
Essayer:
123-(?:(apple|banana|)-|)456
Cela correspondra à une apple
, à une banana
ou à une chaîne vide, et à la suite, il y aura un tiret 0 ou 1. J’avais tort de ne pas avoir besoin d’un groupe de capture. Que je suis bête.
J’ai modifié l’une des réponses (par @ op1ekun):
123-(apple(?=-)|banana(?=-)|(?!-))-?456
La raison en est que la réponse de @ op1ekun correspond également à "123-apple456"
, sans le trait d’union après apple.
Essaye ça:
/\d{3}-(?:(apple|banana)-)?\d{3}/
De loin le plus simple (fonctionne pour python) est '123-(apple|banana)-?456'
.