155 votes

Regex exactement n OU m fois

Considérons l'expression régulière suivante, où X es tous regex.

X{n}|X{m}

Cette expression rationnelle vérifierait la présence des éléments suivants X se produisant exactement n o m fois.

Existe-t-il un quantificateur d'expressions rationnelles qui permette de tester la présence d'une occurrence X exactement n o m fois ?

0 votes

Non. Deux occurrences de X est ce qu'il y a de mieux pour les m , n .

1 votes

Si c'était mon problème, j'essaierais d'utiliser les références inverses des expressions rationnelles et je commencerais par (X)\1{n-1}(?:\1{m-n-1}) . Je sais que cela correspond X au moins une fois, mais pour commencer, essayez cette chose simple, puis affinez en utilisant des "lookaheads" ou des "lookbehinds" au lieu de "lookaheads". (X) .

122voto

Mark Byers Points 318575

Il n'existe pas de quantificateur unique qui signifie "exactement m ou n fois". La façon dont vous procédez est correcte.

Une autre possibilité est de le faire :

X{m}(X{k})?

m < n y k est la valeur de n-m .

106voto

Jan Dvorak Points 14371

Voici la liste complète des quantificateurs (réf. http://www.regular-expressions.info/reference.html )

  • ? , ?? - 0 ou 1 occurrence ( ?? est paresseux, ? est gourmand)
  • * , *? - un nombre quelconque d'occurrences
  • + , +? - au moins une occurrence
  • {n} - exactement n occurrences
  • {n,m} - n a m occurrences, incluses
  • {n,m}? - n a m occurrences, paresseux
  • {n,} , {n,}? - au moins n occurrence

Pour obtenir "exactement N ou M", il faut écrire deux fois la regex quantifiée, sauf si m,n sont spéciaux :

  • X{n,m} si m = n+1
  • (?:X{n}){1,2} si m = 2n
  • ...

2 votes

Pourquoi la ?: nécessaires dans le cas où m = 2n exemple ? Pour ma part, cela semble fonctionner sans problème.

11 votes

@erb si vous omettez ?: le groupe devient un groupe de capture. Outre le fait que le moteur de regex se souvient de choses qu'il n'est pas obligé de faire, si vous avez des groupes de capture après celui-ci, leurs identifiants changeront. Si vous utilisez vos expressions rationnelles pour la substitution, vous devrez ajuster le remplacement.

20voto

Bergi Points 104242

Non, un tel quantificateur n'existe pas. Mais je le restructurerais en /X{m}(X{m-n})?/ pour éviter les problèmes de backtracking .

8voto

DanDan Points 426

Très vieux post, mais j'aimerais contribuer à quelque chose qui pourrait être utile. J'ai essayé exactement comme indiqué dans la question et cela fonctionne, mais il y a un problème : L'ordre des quantités est important. Considérez ceci :

#[a-f0-9]{6}|#[a-f0-9]{3}

Cette fonction permet de trouver toutes les occurrences des codes de couleur hexadécimaux (qui comportent 3 ou 6 chiffres). Mais lorsque je l'inverse comme ceci

#[a-f0-9]{3}|#[a-f0-9]{6}

il ne trouvera que les 3 chiffres ou les 3 premiers chiffres des 6 chiffres. C'est logique et un pro de la Regex pourrait s'en apercevoir immédiatement, mais pour beaucoup, cela peut être un comportement étrange. Certaines fonctions Regex avancées permettent d'éviter ce piège, quel que soit l'ordre, mais tout le monde n'est pas familiarisé avec les modèles Regex.

4voto

Enhardened Points 84

TLDR ; (?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

On dirait que vous voulez "x n fois" ou "x m fois", je pense qu'une traduction littérale en regex serait (x{n}|x{m}). Comme ceci https://regex101.com/r/vH7yL5/1

ou, dans le cas où vous pouvez avoir une séquence de plus de m "x" (en supposant que m > n), vous pouvez ajouter "suivi d'aucun "x"" et "suivi d'aucun "x", ce qui se traduit par [^x](x{n}|x{m})[^x] mais cela supposerait qu'il y ait toujours un personnage derrière et après les "x". Comme vous pouvez le voir ici : https://regex101.com/r/bB2vH2/1

vous pouvez le remplacer par (?:[^x]|^)(x{n}|x{m})(?:[^x]|$) ce qui se traduit par "suivant pas de 'x' ou suivant le début de la ligne" et "suivi par pas de 'x' ou suivi par la fin de la ligne". Cependant, il ne fera pas correspondre deux séquences avec seulement un caractère entre elles (parce que la première correspondance nécessiterait un caractère après, et la seconde un caractère avant), comme vous pouvez le voir ici : https://regex101.com/r/oC5oJ4/1

Enfin, pour faire correspondre le caractère éloigné, vous pouvez ajouter un regard positif avant (?=) sur le "pas de 'x' après" ou un regard positif arrière (?<=) sur le "pas de 'x' avant", comme ceci : https://regex101.com/r/mC4uX3/1

(?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

De cette façon, vous n'obtiendrez que le nombre exact de "x" que vous souhaitez.

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