Quelle est la différence entre les crochets et les parenthèses dans une expression régulière?

Voici une expression régulière que j'ai créée pour utiliser en JavaScript:

var reg_num = /^(7|8|9)d{9}$/

Voici une autre suggestion de mon membre d'équipe.

var reg_num = /^[7|8|9][d]{9}$/

La règle est de valider un numéro de téléphone:

  • il ne doit être que de dix numéros.
  • le premier numéro est supposé être un 7, 8 ou 9.
75
demandé sur Tim Pietzcker 2012-03-21 13:21:00

3 réponses

ces règles sont équivalentes (à des fins de correspondance):

  • /^(7|8|9)\d{9}$/
  • /^[789]\d{9}$/
  • /^[7-9]\d{9}$/

L'explication:

  • (a|b|c) est un " ou "regex et signifie" a ou b ou c", bien que la présence de crochets, nécessaires pour le ou, aussi capture le chiffre. Être strictement équivalent, vous coderiez (?:7|8|9) pour en faire un non groupe de capture.

  • [abc] est une "classe de caractères" qui signifie "n'importe quel caractère de a,b ou c" (une classe de caractères peut utiliser des fourchettes, p.ex. [a-d] = [abcd] )

la raison pour laquelle ces regexes sont similaires est qu'une classe de caractères est un raccourci pour un " ou " (mais seulement pour les caractères simples). Dans une alternance, vous pouvez aussi faire quelque chose comme (abc|def) qui ne traduit pas à une classe de caractères.

91
répondu Bohemian 2017-08-30 16:21:15

le Conseil de votre équipe est presque exact, sauf pour l'erreur qu'il a faite. Une fois que vous découvrez pourquoi, vous ne l'oublierez jamais. Jetez un oeil à cette erreur.

/^(7|8|9)\d{9}$/

ce Que cela fait:

  • ^ et $ désigne ancré matches, qui affirme que le sous-modèle entre ces ancres sont le match en entier. La chaîne ne correspond si le sous-modèle correspond à l'intégralité de cela, non pas seulement d'une section.
  • () indique un groupe de capture .
  • 7|8|9 correspond à 7 , 8 , ou 9 . Il le fait avec alternations , ce que fait l'opérateur | - alternant entre les alternations. Ce retour entre les alternations: si la première n'est pas assortie, le moteur doit revenir avant que l'emplacement de l'indicateur se déplace pendant le match de l'alternance, de continuer à correspondre à la prochaine alternance; alors que la classe de caractère peut avancer séquentiellement. voir ce match sur un moteur regex avec des optimisations désactivées:
Pattern: (r|f)at
Match string: carat

alternations

Pattern: [rf]at
Match string: carat

class

  • \d{9} correspond à neuf chiffres. \d est un metacharacter en désavantage numérique, qui correspond à tous les chiffres.
/^[7|8|9][\d]{9}$/

Regardez ce qu'il fait:

  • ^ et $ désigne ancré correspond aussi.
  • [7|8|9] est une classe de caractères . Tous les caractères de la liste 7 , | , 8 , | , ou 9 peut être assorti, ainsi le | a été ajouté incorrectement. Cela correspond sans retour en arrière.
  • [\d] est une classe de caractères qui habite le metacharacter \d . La combinaison de l'utilisation d'une classe de caractères et un seul caractère de remplacement est une mauvaise idée, par la manière, puisque la couche d'abstraction peut ralentir le match, mais ce n'est qu'un détail d'implémentation et ne s'applique qu'à un petit nombre de regex implémentations. JavaScript n'en est pas un, mais il fait le subpattern légèrement plus long.
  • {9} indique que la construction précédente est répétée neuf fois au total.

le regex optimal est /^[789]\d{9}$/ , parce que /^(7|8|9)\d{9}$/ capture inutilement qui impose une diminution de performance sur la plupart des implémentations regex ( se trouve être un, considérant la question utilise le mot-clé var en code, ce est probablement JavaScript). L'utilisation de qui fonctionne sur PCRE pour la correspondance preg optimisera loin le manque de retracking, cependant nous ne sommes pas en PHP non plus, donc en utilisant les classes [] au lieu d'alternations | donne un bonus de performance que le match ne recule pas, et donc les deux correspond et échoue plus vite qu'en utilisant votre expression régulière précédente.

45
répondu Unihedron 2016-04-14 10:44:16

les deux premiers exemples agissent très différemment si vous les remplacez par quelque chose. Si vous concordez sur ce point:

str = str.replace(/^(7|8|9)/ig,''); 

vous remplaceriez 7 ou 8 ou 9 par la chaîne vide.

Si vous correspondez à ce

str = str.replace(/^[7|8|9]/ig,''); 

vous remplacerez 7 ou 8 ou 9 ou la barre verticale!!!! par la chaîne vide.

je viens de le découvrir à la dure.

8
répondu Sheila 2013-06-20 19:02:26