Regex pour correspondre à un chiffre deux ou quatre fois

95

C'est une question simple sur les expressions régulières, mais je ne trouve pas la réponse.

Je veux déterminer si un nombre apparaît dans l'ordre exactement deux ou quatre fois. Quelle syntaxe puis-je utiliser?

\d{what goes here?}

J'ai essayé \d{2,4}, mais cette expression accepte également trois chiffres.

Renato Dinhani
la source
Par exemple, pour correspondre à deux ou à quatre chiffres année .
DavidRR
Que voulez-vous que la chaîne if soit abc 123 xyz? Doit-il correspondre 12parce que c'est exactement deux chiffres dans l'ordre? Ou ne devrait-il pas, car 12fait partie d'une séquence de chiffres plus grande 123qui elle-même n'est ni 2 ni 4? Si je devais deviner, je pense que vous voulez ce dernier comportement, mais ce n'est pas clair dans votre question. Des exemples et / ou une spécification plus claire seraient utiles. Même question pour abc 12345 def... que doit-il se passer là-bas?
Jean-François Corbett

Réponses:

144

Il n'y a pas de syntaxe spécifique pour cela, mais il existe de nombreuses façons de le faire:

(?:\d{4}|\d{2})    <-- alternation: four digits or two
\d{2}(?:\d{2})?    <-- two digits, and optionally two more
(?:\d{2}){1,2}     <-- two digits, times one or two
Ruakh
la source
1
Personnellement, je n'ai pensé qu'à la \d{2}(?:\d{2})?solution dès le départ - belle variété de ceux-ci - la dernière, en particulier, semble très agréable et évolutive.
Nightfirecat
3
+1 pour être conscient de l'ordre nécessaire lorsque vous utilisez l'alternance pour faire correspondre d'abord 4 chiffres, puis 2 chiffres. Aussi bon travail pour les autres variantes.
Ahmad Mageed
9
Pour tous ceux qui, comme moi, ne comprenaient pas l'utilisation de (?:ceci, lance un "groupe non capturant" (un groupe qui n'est pas destiné à être référencé dans une instruction replace). Vous pouvez également simplement utiliser des parenthèses, mais celles-ci créeront un groupe de capture. Plus de détails ici: stackoverflow.com/questions/3512471/non-capturing-group
Jeremy Moritz
Ceux-ci afficheront le même résultat pour "333" et "33"
Dan
1
@Dan: ces expressions rationnelles ne correspondent pas à la chaîne complète "333". Vous utilisez peut-être par erreur la fonctionnalité "trouver la sous-chaîne correspondante" de votre bibliothèque de regex, plutôt que sa fonctionnalité "vérifier si la chaîne complète correspond". Vous devriez consulter sa documentation.
ruakh
3
(?<!\d)(\d{2}|\d{4})(?!\d)

C'est la bonne façon de procéder. La réponse acceptée est fausse.

Il correspondrait à 3 chiffres (ou 5). C'est donc faux à mes yeux .

1) Vérifiez qu'il n'y a pas de chiffre avant une séquence de 2 ou 4 chiffres, ou après une séquence de deux ou quatre chiffres.

  • (<!) la syntaxe est négative.

  • (?!) la syntaxe est une anticipation négative.

Ce qui précède fonctionnerait pour la corde médiane:

Si votre chaîne de recherche n'a pas de contenu autour d'elle, vous pouvez utiliser les ancres de chaîne ^et de $début et de fin:

^\d{4}$|^\d{2}$
JGFMK
la source
1
Je ne dirais pas que la réponse acceptée est fausse. Je dirais que la question n'est pas claire et que cette réponse en répond à une interprétation valable. Votre réponse aborde une autre interprétation valable (qui, à mon avis, est plus vraisemblable - mais apparemment le demandeur ne l'a pas fait ...).
Jean-François Corbett
2
"Cela correspondrait à 3 chiffres" n'est pas tout à fait exact. Je pense que vous voulez dire "Cela correspondrait à une sous-séquence à 2 chiffres d'une séquence à 3 chiffres."
Jean-François Corbett
1
De plus, votre réponse ne fonctionne pas tout à fait comme prévu sur des séquences de 5 chiffres ou plus . Je ne suis pas un expert en regex, mais je suppose qu'une façon de résoudre ce problème est de faire en sorte que le lookahead / behind négatif s'applique aux deux cas (séquences à 2 et 4 chiffres):(?<!\d)(\d{2}|\d{4})(?!\d)
Jean-François Corbett
Je pense que vous avez raison sur les 5 chiffres. Merci pour cette correction. Va réparer ça.
JGFMK
^\d{4}$|^\d{2}$serait un moyen potentiel de résoudre ce problème. Comme le ferait^\d{2}(?!\d)|^\d{4}(?!\d)
JGFMK