Compartir a través de


Cuantificadores

Los cuantificadores especifican cuántas instancias de un carácter, un grupo o una clase de caracteres debe haber en la entrada para que se encuentre una coincidencia. En la tabla siguiente se enumeran los cuantificadores admitidos por .NET Framework.

Cuantificador expansivo

Cuantificador no expansivo

Descripción

*

*?

Busca cero o más coincidencias.

+

+?

Busca una o varias coincidencias.

?

??

Busca cero o una coincidencia.

{}n

{}?n

Busca exactamente n coincidencias.

{,}n

{,}?n

Busca al menos n coincidencias.

{n,m}

{n,m}?

Busca de n a m coincidencias.

Las cantidades n y m son constantes de tipo entero. Normalmente, los cuantificadores son expansivos; hacen que el motor de expresiones regulares busca coincidencias con tantas apariciones de modelos concretos como sea posible. Anexar el carácter ? a un cuantificador lo hace no expansivo; hace que el motor de expresiones regulares coincida con el mínimo de apariciones posible. Para obtener una descripción de las diferencias que existen entre los dos tipos de cuantificadores, vea la sección Cuantificaciones expansivos y no expansivos más adelante en este tema.

Nota importanteImportante

La anidación de cuantificadores (como hace, por ejemplo, el patrón de expresión regular (a*)*) puede incrementar el número de comparaciones que debe realizar el motor de expresiones regulares, como función exponencial del número de caracteres de la cadena de entrada.Para obtener más información sobre este comportamiento y sus soluciones alternativas, vea Retroceso.

Cuantificadores de expresiones regulares

En las secciones siguientes se enumeran los cuantificadores admitidos en las expresiones regulares de .NET Framework.

NotaNota

Si se encuentran los caracteres *, +?, { y } en un modelo de expresión regular, el motor de expresiones regulares los interpretará como cuantificadores o como parte de construcciones de cuantificador, a menos que estén incluidos en una clase de caracteres.Para interpretarlos como caracteres literales fuera de una clase de caracteres, debe aplicarlos una secuencia de escape precediéndolos con una barra diagonal inversa.Por ejemplo, la cadena \* en un modelo de expresión regular se interpreta como un carácter de asterisco ("*") literal.

Busca cero o más coincidencias: *

El cuantificador * coincide cero o más veces con el elemento anterior. Es equivalente al cuantificador {0,}. * es un cuantificador expansivo cuyo equivalente no expansivo es *?.

En el siguiente ejemplo se muestra esta expresión regular. De los nueve dígitos de la cadena de entrada, cinco coinciden con el modelo y cuatro, (95, 929, 9129 y 9919) no.

Dim pattern As String = "\b91*9*\b"   
Dim input As String = "99 95 919 929 9119 9219 999 9919 91119"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next     
' The example displays the following output:   
'       '99' found at position 0.
'       '919' found at position 6.
'       '9119' found at position 14.
'       '999' found at position 24.
'       '91119' found at position 33.
string pattern = @"\b91*9*\b";   
string input = "99 95 919 929 9119 9219 999 9919 91119";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

// The example displays the following output:   
//       '99' found at position 0.
//       '919' found at position 6.
//       '9119' found at position 14.
//       '999' found at position 24.
//       '91119' found at position 33.

El modelo de expresión regular se define como se muestra en la tabla siguiente.

Modelo

Descripción

\b

Empezar en un límite de palabras.

91*

Busca una coincidencia con un "9" seguido de cero o más caracteres "1".

9*

Busca una coincidencia con cero o más caracteres "9".

\b

Finalizar en un límite de palabras.

Busca una o varias coincidencias: +

El cuantificador + coincide una o más veces con el elemento anterior. Equivale a {1,}. + es un cuantificador expansivo cuyo equivalente no expansivo es +?.

Por ejemplo, la expresión regular \ban+\w*?\b intenta encontrar coincidencias de palabras enteras que comienzan con la letra a seguida de una o varias instancias de la letra n. En el siguiente ejemplo se muestra esta expresión regular. La expresión regular coincide con las palabras an, annual, announcement y antique y, como cabía esperar, no coincide con autumn ni con all.

Dim pattern As String = "\ban+\w*?\b"

Dim input As String = "Autumn is a great time for an annual announcement to all antique collectors."
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next   
' The example displays the following output:   
'       'an' found at position 27.
'       'annual' found at position 30.
'       'announcement' found at position 37.
'       'antique' found at position 57.      
string pattern = @"\ban+\w*?\b";

string input = "Autumn is a great time for an annual announcement to all antique collectors.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

// The example displays the following output:   
//       'an' found at position 27.
//       'annual' found at position 30.
//       'announcement' found at position 37.
//       'antique' found at position 57.      

El modelo de expresión regular se define como se muestra en la tabla siguiente.

Modelo

Descripción

\b

Empezar en un límite de palabras.

an+

Busca una coincidencia de una "a" seguida de uno o varios caracteres "n".

\w*?

Busca cero o más coincidencias de un carácter de palabra, pero limitando el número de coincidencias al menor número posible.

\b

Finalizar en un límite de palabras.

Busca cero o una coincidencia: ?

El cuantificador ? coincide cero o una vez con el elemento anterior. Equivale a {0,1}. ? es un cuantificador expansivo cuyo equivalente no expansivo es ??.

Por ejemplo, la expresión regular \ban?\b intenta encontrar coincidencias de palabras enteras que comienzan con la letra a seguida de cero o una instancia de la letra n. En otras palabras, intenta buscar coincidencias con las palabras a y an. En el siguiente ejemplo se muestra esta expresión regular.

Dim pattern As String = "\ban?\b"
Dim input As String = "An amiable animal with a large snount and an animated nose."
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next  
' The example displays the following output:   
'       'An' found at position 0.
'       'a' found at position 23.
'       'an' found at position 42.
string pattern = @"\ban?\b";
string input = "An amiable animal with a large snount and an animated nose.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

// The example displays the following output:   
//        'An' found at position 0.
//        'a' found at position 23.
//        'an' found at position 42.

El modelo de expresión regular se define como se muestra en la tabla siguiente.

Modelo

Descripción

\b

Empezar en un límite de palabras.

an?

Busca una coincidencia de una "a" seguida de cero o un carácter "n".

\b

Finalizar en un límite de palabras.

Busca exactamente n coincidencias: {n}

El cuantificador{n} coincide con el elemento anterior exactamente n veces, donde n es un entero. {n} es un cuantificador expansivo cuyo equivalente no expansivo es {n}?.

Por ejemplo, la expresión regular \b\d+\,\d{3}\b intenta encontrar coincidencias de un límite de palabra seguido de uno o varios dígitos decimales, que, a su vez, van seguidos por tres dígitos decimales seguidos por un límite de palabra. En el siguiente ejemplo se muestra esta expresión regular.

Dim pattern As String = "\b\d+\,\d{3}\b"
Dim input As String = "Sales totaled 103,524 million in January, " + _
                      "106,971 million in February, but only " + _
                      "943 million in March."
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next     
' The example displays the following output:   
'       '103,524' found at position 14.
'       '106,971' found at position 45.
string pattern = @"\b\d+\,\d{3}\b";
string input = "Sales totaled 103,524 million in January, " + 
                      "106,971 million in February, but only " + 
                      "943 million in March.";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:   
//        '103,524' found at position 14.
//        '106,971' found at position 45.

El modelo de expresión regular se define como se muestra en la tabla siguiente.

Modelo

Descripción

\b

Empezar en un límite de palabras.

\d+

Buscar coincidencias con uno o más dígitos decimales.

\,

Busca una coincidencia con un carácter de coma.

\d{3}

Buscar coincidencias con tres dígitos decimales.

\b

Finalizar en un límite de palabras.

Busca al menos n coincidencias: {n,}

El cuantificador {n,} coincide con el elemento anterior al menos n veces, donde n es un entero. {n,} es un cuantificador expansivo cuyo equivalente no expansivo es {n}?.

Por ejemplo, la expresión regular \b\d{2,}\b\D+ intenta encontrar coincidencias con un límite de palabra seguido por lo menos de dos dígitos, que, a su vez, van seguidos de un límite de palabra y un carácter no numérico. En el siguiente ejemplo se muestra esta expresión regular. La expresión regular no coincide con la frase "7 days" porque solo contiene un dígito decimal, pero coincide correctamente con las frases "10 weeks and 300 years".

 Dim pattern As String = "\b\d{2,}\b\D+"  
 Dim input As String = "7 days, 10 weeks, 300 years"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       '10 weeks, ' found at position 8.
'       '300 years' found at position 18.
string pattern = @"\b\d{2,}\b\D+";   
string input = "7 days, 10 weeks, 300 years";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        '10 weeks, ' found at position 8.
//        '300 years' found at position 18.

El modelo de expresión regular se define como se muestra en la tabla siguiente.

Modelo

Descripción

\b

Empezar en un límite de palabras.

\d{2,}

Busca una coincidencia de al menos dos dígitos decimales.

\b

Hacer coincidir con un límite de palabras.

\D+

Busca una coincidencia de al menos un dígito no decimal.

Busca de n a m coincidencias: {n,m}

El cuantificador {n,m} coincide con el elemento anterior al menos veces, pero no más de m veces, donde n y m son enteros. {n,m} es un cuantificador expansivo cuyo cuantificador no expansivo es {n,m}?.

En el ejemplo siguiente, la expresión regular (00\s){2,4} intenta encontrar coincidencias entre dos y cuatro ocurrencias de dos ceros seguidos de un espacio. Observe que la parte final de la cadena de entrada incluye este modelo cinco veces en lugar del máximo de cuatro. Sin embargo, solo la parte inicial de esta subcadena (hasta el espacio y el quinto par de ceros) coincide con el modelo de la expresión regular.

Dim pattern As String = "(00\s){2,4}"
Dim input As String = "0x00 FF 00 00 18 17 FF 00 00 00 21 00 00 00 00 00"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       '00 00 ' found at position 8.
'       '00 00 00 ' found at position 23.
'       '00 00 00 00 ' found at position 35.
string pattern = @"(00\s){2,4}";
string input = "0x00 FF 00 00 18 17 FF 00 00 00 21 00 00 00 00 00";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        '00 00 ' found at position 8.
//        '00 00 00 ' found at position 23.
//        '00 00 00 00 ' found at position 35.

Busca cero o más coincidencias (coincidencia no expansiva): *?

El cuantificador *? coincide con el elemento anterior ninguna o alguna vez, pero el menor número de veces que sea posible. Es el equivalente no expansivo del cuantificador expansivo *.

En el ejemplo siguiente, la expresión regular \b\w*?oo\w*?\b coincide con todas las palabras que contienen la cadena oo.

 Dim pattern As String = "\b\w*?oo\w*?\b"
 Dim input As String = "woof root root rob oof woo woe"
 For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
 Next 
 ' The example displays the following output:
'       'woof' found at position 0.
'       'root' found at position 5.
'       'root' found at position 10.
'       'oof' found at position 19.
'       'woo' found at position 23.
 string pattern = @"\b\w*?oo\w*?\b";
 string input = "woof root root rob oof woo woe";
 foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

 //  The example displays the following output:
//        'woof' found at position 0.
//        'root' found at position 5.
//        'root' found at position 10.
//        'oof' found at position 19.
//        'woo' found at position 23.

El modelo de expresión regular se define como se muestra en la tabla siguiente.

Modelo

Descripción

\b

Empezar en un límite de palabras.

\w*?

Busca una coincidencia con cero o más caracteres de palabra, pero con la menor cantidad posible de caracteres.

oo

Busca una coincidencia con la cadena "oo".

\w*?

Busca una coincidencia con cero o más caracteres de palabra, pero con la menor cantidad posible de caracteres.

\b

Finalizar en un límite de palabras.

Busca una o varias coincidencias (coincidencia no expansiva): +?

El cuantificador +? coincide con el elemento anterior una o más veces, pero el menor número de veces que sea posible. Es el equivalente no expansivo del cuantificador expansivo +.

Por ejemplo, la expresión regular \b\w+?\b coincide con uno o varios caracteres separados por límites de palabra. En el siguiente ejemplo se muestra esta expresión regular.

 Dim pattern As String = "\b\w+?\b"
 Dim input As String = "Aa Bb Cc Dd Ee Ff"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       'Aa' found at position 0.
'       'Bb' found at position 3.
'       'Cc' found at position 6.
'       'Dd' found at position 9.
'       'Ee' found at position 12.
'       'Ff' found at position 15.
string pattern = @"\b\w+?\b";
string input = "Aa Bb Cc Dd Ee Ff";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        'Aa' found at position 0.
//        'Bb' found at position 3.
//        'Cc' found at position 6.
//        'Dd' found at position 9.
//        'Ee' found at position 12.
//        'Ff' found at position 15.

Busca cero o una coincidencia (coincidencia no expansiva): ??

El cuantificador ?? coincide con el elemento anterior ninguna o una vez, pero el menor número de veces que sea posible. Es el equivalente no expansivo del cuantificador expansivo ?.

Por ejemplo, la expresión regular ^\s*(System.)??Console.Write(Line)??\(?? intenta hacer coincidir las cadenas "Console.Write" o "Console.WriteLine". La cadena también puede incluir "System." delante de "Console", y puede ir seguida de un paréntesis de apertura. La cadena debe estar al comienzo de una línea, aunque puede ir precedida de un espacio en blanco. En el siguiente ejemplo se muestra esta expresión regular.

Dim pattern As String = "^\s*(System.)??Console.Write(Line)??\(??"
Dim input As String = "System.Console.WriteLine(""Hello!"")" + vbCrLf + _
                      "Console.Write(""Hello!"")" + vbCrLf + _
                      "Console.WriteLine(""Hello!"")" + vbCrLf + _
                      "Console.ReadLine()" + vbCrLf + _
                      "   Console.WriteLine"
For Each match As Match In Regex.Matches(input, pattern, _
                                         RegexOptions.IgnorePatternWhitespace Or RegexOptions.IgnoreCase Or RegexOptions.MultiLine)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       'System.Console.Write' found at position 0.
'       'Console.Write' found at position 36.
'       'Console.Write' found at position 61.
'       '   Console.Write' found at position 110.
string pattern = @"^\s*(System.)??Console.Write(Line)??\(??";
string input = "System.Console.WriteLine(\"Hello!\")\n" + 
                      "Console.Write(\"Hello!\")\n" + 
                      "Console.WriteLine(\"Hello!\")\n" + 
                      "Console.ReadLine()\n" + 
                      "   Console.WriteLine";
foreach (Match match in Regex.Matches(input, pattern, 
                                      RegexOptions.IgnorePatternWhitespace | 
                                      RegexOptions.IgnoreCase | 
                                      RegexOptions.Multiline))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        'System.Console.Write' found at position 0.
//        'Console.Write' found at position 36.
//        'Console.Write' found at position 61.
//        '   Console.Write' found at position 110.

El modelo de expresión regular se define como se muestra en la tabla siguiente.

Modelo

Descripción

^

Busca una coincidencia con el comienzo del flujo de entrada.

\s*

Busca coincidencias con cero o más caracteres de espacio en blanco.

(System.)??

Busca cero o una coincidencia con la cadena "System.".

Console.Write

Busca coincidencias con la cadena "Console.Write".

(Line)??

Busca cero o una coincidencia con la cadena "Line".

\(??

Busca cero o una coincidencia con el paréntesis de apertura.

Busca exactamente n coincidencias (coincidencia no expansiva): {n}?

el cuantificador {n}? coincide con el elemento anterior exactamente n veces, donde n es un entero. Es el equivalente no expansivo del cuantificador expansivo {}+.

En el ejemplo siguiente, la expresión regular \b(\w{3,}?\.){2}?\w{3,}?\b se usa para identificar una dirección de sitio web. Observe que coincide con "www.microsoft.com" y "msdn.microsoft.com", pero no coincide con "mywebsite" ni "mycompany.com".

 Dim pattern As String = "\b(\w{3,}?\.){2}?\w{3,}?\b"
 Dim input As String = "www.microsoft.com msdn.microsoft.com mywebsite mycompany.com"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next     
' The example displays the following output:
'       'www.microsoft.com' found at position 0.
'       'msdn.microsoft.com' found at position 18.
string pattern = @"\b(\w{3,}?\.){2}?\w{3,}?\b";
string input = "www.microsoft.com msdn.microsoft.com mywebsite mycompany.com";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        'www.microsoft.com' found at position 0.
//        'msdn.microsoft.com' found at position 18.

El modelo de expresión regular se define como se muestra en la tabla siguiente.

Modelo

Descripción

\b

Empezar en un límite de palabras.

(\w{3,}? \.)

Busca una coincidencia de al menos 3 caracteres de palabra, pero limitándolos al menor número de caracteres posible, seguidos de un carácter de punto. Éste es el primer grupo de captura.

(\w{3,}? \.){2}?

Busca dos coincidencias con el modelo en el primer grupo, reduciendo el número de coincidencias al menor número posible.

\b

Finalizar la búsqueda de coincidencias en un límite de palabras.

Busca al menos n coincidencias (coincidencia no expansiva): {n,}?

El cuantificador {n,}? coincide con el elemento anterior al menos n veces, donde n es un entero, pero el menor número de veces posible. Es el equivalente no expansivo del cuantificador expansivo {,}.

Vea el ejemplo del cuantificador {n}? que figura en la sección anterior a modo de ejemplo. La expresión regular de ese ejemplo utiliza el cuantificador {n,}para buscar coincidencias con una cadena que tenga al menos tres caracteres seguidos de un punto.

Busca de n a m coincidencias (coincidencia no expansiva): {n,m}?

El cuantificador {n,m}? coincide con el elemento anterior entre n y m veces, donde n y m son enteros, pero el menor número de veces posible. Es el equivalente no expansivo del cuantificador expansivo {n,m}.

En el ejemplo siguiente, la expresión regular \b[A-Z](\w*\s+){1,10}?[.!?] busca coincidencias con frases que contengan entre una y diez palabras. Coincide con todas las frases de la cadena de entrada a excepción de una frase que contiene 18 palabras.

Dim pattern As String = "\b[A-Z](\w*\s?){1,10}?[.!?]"
Dim input As String = "Hi. I am writing a short note. Its purpose is " + _
                      "to test a regular expression that attempts to find " + _
                      "sentences with ten or fewer words. Most sentences " + _
                      "in this note are short."
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       'Hi.' found at position 0.
'       'I am writing a short note.' found at position 4.
'       'Most sentences in this note are short.' found at position 132.
string pattern = @"\b[A-Z](\w*?\s*?){1,10}[.!?]";
string input = "Hi. I am writing a short note. Its purpose is " + 
                      "to test a regular expression that attempts to find " + 
                      "sentences with ten or fewer words. Most sentences " + 
                      "in this note are short.";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        'Hi.' found at position 0.
//        'I am writing a short note.' found at position 4.
//        'Most sentences in this note are short.' found at position 132.

El modelo de expresión regular se define como se muestra en la tabla siguiente.

Modelo

Descripción

\b

Empezar en un límite de palabras.

[A-Z]

Busca una coincidencia de una letra mayúscula de la A a la Z.

(\w*\s+)

Busca una coincidencia con cero o más caracteres de palabra seguidos de uno o varios caracteres de espacio en blanco. Este es el primer grupo de capturas.

{1,10}?

Busca de 1 a 10 coincidencias con el modelo anterior, reduciendo el número de coincidencias al menor número posible.

[.!?]

Busca una coincidencia de cualquiera de los caracteres de puntuación ".", "!" o "?".

Cuantificadores expansivos y no expansivos

Hay varios cuantificadores que tienen dos versiones:

  • Una versión expansiva.

    Un cuantificador expansivo intenta buscar coincidencias con el elemento tantas veces como sea posible.

  • Una versión no expansiva.

    Un cuantificador no expansivo intenta buscar coincidencias con el elemento el menor número de veces posible. Puede convertir un cuantificador expansivo en un cuantificador no expansivo agregando simplemente un ?.

Considere una expresión regular simple con la que se pretende extraer los cuatro últimos dígitos de una cadena de números como los de una tarjeta de crédito. La versión de la expresión regular que utiliza el cuantificador * expansivo es \b.*([0-9]{4})\b. Sin embargo, si una cadena contiene dos números, esta expresión regular buscará coincidencias solo con los cuatro últimos dígitos del segundo número, tal y como se muestra en el ejemplo siguiente.

Dim greedyPattern As String = "\b.*([0-9]{4})\b"
Dim input1 As String = "1112223333 3992991999"
For Each match As Match In Regex.Matches(input1, greedypattern)
   Console.WriteLine("Account ending in ******{0}.", match.Groups(1).Value)
Next
' The example displays the following output:
'       Account ending in ******1999.
string greedyPattern = @"\b.*([0-9]{4})\b";
string input1 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input1, greedyPattern))
   Console.WriteLine("Account ending in ******{0}.", match.Groups[1].Value);

// The example displays the following output:
//       Account ending in ******1999.

La expresión regular no coincide con el primer número porque el cuantificador * intenta buscar coincidencias con el elemento anterior tantas veces como sea posible en toda la cadena y, por tanto, encuentra su coincidencia al final de la cadena.

Éste no es el comportamiento deseado. En su lugar, puede utilizar el cuantificador no expansivo *? para extraer los dígitos de ambos números, tal y como se muestra en el siguiente ejemplo.

Dim lazyPattern As String = "\b.*?([0-9]{4})\b"
Dim input2 As String = "1112223333 3992991999"
For Each match As Match In Regex.Matches(input2, lazypattern)
   Console.WriteLine("Account ending in ******{0}.", match.Groups(1).Value)
Next     
' The example displays the following output:
'       Account ending in ******3333.
'       Account ending in ******1999.
string lazyPattern = @"\b.*?([0-9]{4})\b";
string input2 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input2, lazyPattern))
   Console.WriteLine("Account ending in ******{0}.", match.Groups[1].Value);

// The example displays the following output:
//       Account ending in ******3333.
//       Account ending in ******1999.

En la mayoría de los casos, las expresiones regulares con cuantificadores expansivos y no expansivos devuelven las mismas coincidencias. La mayor parte de las veces, devuelven resultados diferentes cuando se utilizan con el metacarácter comodín (.), que coincide con cualquier carácter.

Cuantificadores y coincidencias vacías

Los cuantificadores *, +, y {n,m}, así como sus homólogos no expansivos, nunca se repiten tras una coincidencia vacía si se ha encontrado el número mínimo de capturas. Esta regla impide que los cuantificadores entren en bucles infinitos de coincidencias de subexpresión vacías cuando el número máximo de capturas posibles del grupo es infinito o casi infinito.

Por ejemplo, el código siguiente muestra el resultado de una llamada al método Regex.Match con el modelo de expresión regular (a?)*, que coincide con cero o un carácter "a", cero o más veces. Tenga en cuenta que el grupo de captura único captura todas las instancias de “a”, así como de String.Empty, pero no hay una segunda coincidencia vacía, porque en la primera el cuantificador deja de repetirse.

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim pattern As String = "(a?)*"
      Dim input As String = "aaabbb"
      Dim match As Match = Regex.Match(input, pattern)
      Console.WriteLine("Match: '{0}' at index {1}", 
                        match.Value, match.Index)
      If match.Groups.Count > 1 Then
         Dim groups As GroupCollection = match.Groups
         For grpCtr As Integer = 1 To groups.Count - 1
            Console.WriteLine("   Group {0}: '{1}' at index {2}", 
                              grpCtr, 
                              groups(grpCtr).Value,
                              groups(grpCtr).Index)
            Dim captureCtr As Integer = 0
            For Each capture As Capture In groups(grpCtr).Captures
               captureCtr += 1
               Console.WriteLine("      Capture {0}: '{1}' at index {2}", 
                                 captureCtr, capture.Value, capture.Index)
            Next
         Next 
      End If   
   End Sub
End Module
' The example displays the following output:
'       Match: 'aaa' at index 0
'          Group 1: '' at index 3
'             Capture 1: 'a' at index 0
'             Capture 2: 'a' at index 1
'             Capture 3: 'a' at index 2
'             Capture 4: '' at index 3
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = "(a?)*";
      string input = "aaabbb";
      Match match = Regex.Match(input, pattern);
      Console.WriteLine("Match: '{0}' at index {1}", 
                        match.Value, match.Index);
      if (match.Groups.Count > 1) {
         GroupCollection groups = match.Groups;
         for (int grpCtr = 1; grpCtr <= groups.Count - 1; grpCtr++) {
            Console.WriteLine("   Group {0}: '{1}' at index {2}", 
                              grpCtr, 
                              groups[grpCtr].Value,
                              groups[grpCtr].Index);
            int captureCtr = 0;
            foreach (Capture capture in groups[grpCtr].Captures) {
               captureCtr++;
               Console.WriteLine("      Capture {0}: '{1}' at index {2}", 
                                 captureCtr, capture.Value, capture.Index);
            }
         } 
      }   
   }
}
// The example displays the following output:
//       Match: 'aaa' at index 0
//          Group 1: '' at index 3
//             Capture 1: 'a' at index 0
//             Capture 2: 'a' at index 1
//             Capture 3: 'a' at index 2
//             Capture 4: '' at index 3

Para ver la diferencia práctica entre un grupo de captura que define un número mínimo y máximo de capturas y otro que define un número de capturas fijo, considere los patrones de expresiones regulares (a\1|(?(1)\1)){0,2} y (a\1|(?(1)\1)){2}. Ambas expresiones regulares constan de un único grupo de capturas, que se define como se muestra en la tabla siguiente.

Modelo

Descripción

(a\1

Hacer coincidir “a” con el valor del primer grupo capturado...

|(?(1)

… o prueba si se ha definido el primer grupo capturado. (Observe que la construcción (?(1) no define un grupo de captura).

\1))

Si el primer grupo capturado existe, coincide con su valor. Si el grupo no existe, este coincidirá con String.Empty.

La primera expresión regular intenta coincidir con este modelo entre cero y dos veces; la segunda, exactamente dos veces. Dado que el primer modelo alcanza el número mínimo de capturas con su primera captura de String.Empty, nunca se repite para intentar hacer coincidir a\1; el cuantificador {0,2} sólo permite coincidencias vacías en la última iteración. En cambio, la segunda expresión regular coincide con “a” porque evalúa a\1 por segunda vez; el número mínimo de iteraciones, 2, obliga al motor a repetir después de una coincidencia vacía.

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim pattern, input As String

      pattern = "(a\1|(?(1)\1)){0,2}"
      input = "aaabbb" 

      Console.WriteLine("Regex pattern: {0}", pattern)
      Dim match As Match = Regex.Match(input, pattern)
      Console.WriteLine("Match: '{0}' at position {1}.", 
                        match.Value, match.Index)
      If match.Groups.Count > 1 Then
         For groupCtr As Integer = 1 To match.Groups.Count - 1
            Dim group As Group = match.Groups(groupCtr)         
            Console.WriteLine("   Group: {0}: '{1}' at position {2}.", 
                              groupCtr, group.Value, group.Index)
            Dim captureCtr As Integer = 0
            For Each capture As Capture In group.Captures
               captureCtr += 1
               Console.WriteLine("      Capture: {0}: '{1}' at position {2}.", 
                                 captureCtr, capture.Value, capture.Index)
            Next   
         Next
      End If
      Console.WriteLine()

      pattern = "(a\1|(?(1)\1)){2}"
      Console.WriteLine("Regex pattern: {0}", pattern)
      match = Regex.Match(input, pattern)
         Console.WriteLine("Matched '{0}' at position {1}.", 
                           match.Value, match.Index)
      If match.Groups.Count > 1 Then
         For groupCtr As Integer = 1 To match.Groups.Count - 1
            Dim group As Group = match.Groups(groupCtr)         
            Console.WriteLine("   Group: {0}: '{1}' at position {2}.", 
                              groupCtr, group.Value, group.Index)
            Dim captureCtr As Integer = 0
            For Each capture As Capture In group.Captures
               captureCtr += 1
               Console.WriteLine("      Capture: {0}: '{1}' at position {2}.", 
                                 captureCtr, capture.Value, capture.Index)
            Next   
         Next
      End If
   End Sub
End Module
' The example displays the following output:
'       Regex pattern: (a\1|(?(1)\1)){0,2}
'       Match: '' at position 0.
'          Group: 1: '' at position 0.
'             Capture: 1: '' at position 0.
'       
'       Regex pattern: (a\1|(?(1)\1)){2}
'       Matched 'a' at position 0.
'          Group: 1: 'a' at position 0.
'             Capture: 1: '' at position 0.
'             Capture: 2: 'a' at position 0.
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern, input;

      pattern = @"(a\1|(?(1)\1)){0,2}";
      input = "aaabbb"; 

      Console.WriteLine("Regex pattern: {0}", pattern);
      Match match = Regex.Match(input, pattern);
      Console.WriteLine("Match: '{0}' at position {1}.", 
                        match.Value, match.Index);
      if (match.Groups.Count > 1) {
         for (int groupCtr = 1; groupCtr <= match.Groups.Count - 1; groupCtr++)
         {
            Group group = match.Groups[groupCtr];         
            Console.WriteLine("   Group: {0}: '{1}' at position {2}.", 
                              groupCtr, group.Value, group.Index);
            int captureCtr = 0;
            foreach (Capture capture in group.Captures) {
               captureCtr++;
               Console.WriteLine("      Capture: {0}: '{1}' at position {2}.", 
                                 captureCtr, capture.Value, capture.Index);
            }   
         }
      }
      Console.WriteLine();

      pattern = @"(a\1|(?(1)\1)){2}";
      Console.WriteLine("Regex pattern: {0}", pattern);
      match = Regex.Match(input, pattern);
         Console.WriteLine("Matched '{0}' at position {1}.", 
                           match.Value, match.Index);
      if (match.Groups.Count > 1) {
         for (int groupCtr = 1; groupCtr <= match.Groups.Count - 1; groupCtr++)
         {
            Group group = match.Groups[groupCtr];         
            Console.WriteLine("   Group: {0}: '{1}' at position {2}.", 
                              groupCtr, group.Value, group.Index);
            int captureCtr = 0;
            foreach (Capture capture in group.Captures) {
               captureCtr++;
               Console.WriteLine("      Capture: {0}: '{1}' at position {2}.", 
                                 captureCtr, capture.Value, capture.Index);
            }   
         }
      }
   }
}
// The example displays the following output:
//       Regex pattern: (a\1|(?(1)\1)){0,2}
//       Match: '' at position 0.
//          Group: 1: '' at position 0.
//             Capture: 1: '' at position 0.
//       
//       Regex pattern: (a\1|(?(1)\1)){2}
//       Matched 'a' at position 0.
//          Group: 1: 'a' at position 0.
//             Capture: 1: '' at position 0.
//             Capture: 2: 'a' at position 0.

Vea también

Conceptos

Elementos del lenguaje de expresiones regulares

Retroceso

Historial de cambios

Fecha

Historial

Motivo

Octubre de 2010

Se agregó la sección "Cuantificadores y coincidencias vacías".

Mejora de la información.