web-dev-qa-db-fra.com

Regex exactement n OR m fois

Considérez l'expression régulière suivante, où X est any regex.

X{n}|X{m}

Cette expression rationnelle vérifierait si X se produit exactement n ou m fois.

Existe-t-il un quantificateur de regex capable de tester une occurrence X exactement n ou m fois?

74
Vulcan

Il n'y a pas de quantificateur unique qui signifie "exactement m ou n fois". La façon dont vous le faites est bien.

Une alternative est:

X{m}(X{k})?

m < n et k est la valeur de n-m

68
Mark Byers

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

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

Pour obtenir "exactement N ou M", vous devez é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
  • ...
42
John Dvorak

Non, il n'y a pas de tel quantificateur. Mais je l’ai restructuré en /X{m}(X{m-n})?/ pour éviter des problèmes de retour en arrière .

18
Bergi

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}).Like this https://regex101.com/r/vH7yL5/1

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

vous pouvez le changer en (?:[^x]|^)(x{n}|x{m})(?:[^x]|$), en traduisant "après le 'x' ou après le début de la ligne" et "suivi par le 'non' ou suivi par la fin de la ligne". Néanmoins, il ne correspondra pas à deux séquences avec un seul caractère entre elles (car 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 match à un caractère distant, vous pouvez ajouter un regard positif devant vous (? =) Sur le "non 'x' après" ou un regard positif derrière (? <=) Sur le "non 'x' avant", comme ceci: https://regex101.com/r/mC4uX3/1

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

De cette façon, vous ne ferez correspondre que le nombre exact de 'x que vous voulez.

2
Enhardened

En examinant la réponse d'Enhardened, ils déclarent que leur avant-dernière expression ne correspondra pas à des séquences contenant un seul caractère. Il existe un moyen simple de résoudre ce problème sans utiliser regarder devant/derrière, et cela consiste à remplacer le caractère de début/fin par le caractère de limite. Cela vous permet de faire correspondre les limites de Word, y compris début/fin. En tant que telle, l'expression appropriée devrait être:

(?:[^x]|\b)(x{n}|x{m})(?:[^x]|\b)

Comme vous pouvez le voir ici: https://regex101.com/r/oC5oJ4/2 .

0
rozza2058

Très vieux message, mais j'aimerais apporter quelque chose qui pourrait être utile… .. Je l'ai essayé exactement comme indiqué dans la question et cela fonctionne, mais il y a un problème: L'ordre des quantités questions. Considère ceci:

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

Cela trouvera toutes les occurrences de codes de couleur hexadécimaux (ils ont 3 ou 6 chiffres). Mais quand je le retourne comme ça 

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

il ne trouvera que les 3 chiffres ou les 3 premiers chiffres des 6 chiffres. Cela a du sens et un professionnel de Regex pourrait le remarquer tout de suite, mais pour beaucoup cela pourrait être un comportement particulier. Certaines fonctionnalités avancées de Regex pourraient éviter ce piège quel que soit l'ordre choisi, mais tout le monde n'est pas à genou dans les patterns de Regex.

0
DanDan