¿Cuál es la diferencia entre corchetes y paréntesis en una expresión regular?

Aquí hay una expresión regular que creé para usar en JavaScript:

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

Aquí hay otro sugerido por mi miembro del equipo.

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

La regla es validar un número de teléfono:

  • Debe ser de solo diez números.
  • Se supone que el primer número es cualquiera de 7, 8 o 9.

Estas expresiones regulares son equivalentes (para fines de coincidencia):

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

La explicación:

  • (a|b|c) es una expresión regular “OR” y significa “a o b o c”, aunque la presencia de corchetes, necesarios para el OR, también captura el dígito. Para ser estrictamente equivalente, codificaría (?:7|8|9) para que no sea un grupo de captura.

  • [abc] es una “clase de caracteres” que significa “cualquier carácter de a, boc” (una clase de caracteres puede usar rangos, por ejemplo [ad] = [abcd] )

La razón por la que estas expresiones regulares son similares es que una clase de caracteres es una abreviatura de “o” (pero solo para caracteres individuales). En una alternancia, también puede hacer algo como (abc|def) que no se traduce a una clase de caracteres.

El consejo de su equipo es casi correcto, excepto por el error que cometió. Una vez que descubres por qué, nunca lo olvidarás. Eche un vistazo a este error.

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

Que hace esto?

  • ^ y $ denota coincidencias ancladas, que afirman que el subpatrón entre estos anclajes es la coincidencia completa. La cadena solo coincidirá si el subpatrón coincide con la totalidad, no solo con una sección.
  • () denota un grupo de captura .
  • 7|8|9 denota coincidencia cualquiera de 7 , 8 o 9 . Lo hace con las alternancias , que es lo que el operador de tuberías | does – alternando entre alternancias. Esto retrocede entre las alternancias: si la primera alternancia no coincide, el motor debe regresar antes de que la ubicación del puntero se mueva durante la coincidencia de la alternancia, para continuar coincidiendo con la siguiente alternancia; Mientras que la clase de personaje puede avanzar secuencialmente. Vea esta coincidencia en un motor de expresiones regulares con optimizaciones desactivadas:
 Pattern: (r|f)at Match string: carat 

alternations

 Pattern: [rf]at Match string: carat 

class

  • \d{9} coincide con nueve dígitos. \d es un metacaracter de shorthanded, que coincide con cualquier dígito.
 /^[7|8|9][\d]{9}$/ 

Mira lo que hace:

  • ^ y $ denota coincidencias ancladas también.
  • [7|8|9] es una clase de personaje . Cualquier personaje de la lista 7 , | , 8 , | , o 9 pueden coincidir, por lo tanto | fue agregado incorrectamente Esto coincide sin retroceder.
  • [\d] es una clase de personaje que habita el metacaracter \d . La combinación del uso de una clase de caracteres y un metacarácter único es una mala idea, por cierto, ya que la capa de abstracción puede ralentizar la coincidencia, pero esto es solo un detalle de implementación y solo se aplica a algunas implementaciones de expresiones regulares. JavaScript no es uno, pero hace que el subpatrón sea un poco más largo.
  • {9} indica que la única construcción anterior se repite nueve veces en total.

La expresión regular óptima es /^[789]\d{9}$/ , porque /^(7|8|9)\d{9}$/ captura innecesariamente, lo que impone una disminución del rendimiento en la mayoría de las implementaciones de expresiones regulares ( JavaScript es uno, considerando que la pregunta usa la palabra clave var en el código, esto probablemente sea JavaScript). El uso de php que se ejecuta en PCRE para la coincidencia de preg optimizará la falta de retroceso, sin embargo, tampoco estamos en PHP, por lo que usamos clases [] lugar de alternaciones | le da una bonificación de rendimiento ya que la partida no retrocede, y por lo tanto ambas coincide y falla más rápido que usar su expresión regular anterior.

Los primeros 2 ejemplos actúan de manera muy diferente si los REEMPLAZA por algo. Si coincides en esto:

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

reemplazarías 7, 8 o 9 por la cadena vacía.

Si coincide con esto

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

reemplazarás 7 u 8 o 9 O LA BARRA VERTICAL !!!! por la cuerda vacía.

Acabo de descubrir esto por el camino difícil.