Conceptos básicos de expresión regulares en C ++

Conceptos básicos de expresión regulares en C ++
Considere la siguiente oración en citas: "Aquí está mi hombre."

Esta cadena puede estar dentro de la computadora, y el usuario puede querer saber si tiene la palabra "hombre". Si tiene la palabra hombre, puede querer cambiar la palabra "hombre" a "mujer"; para que la cadena deba leer:

"Aquí está mi mujer."

Hay muchos otros deseos como estos del usuario de la computadora; Algunos son complejos. La expresión regular, abreviada, regex, es el tema del manejo de estos problemas por la computadora. C ++ viene con una biblioteca llamada regex. Entonces, un programa C ++ para manejar a Regex debería comenzar con:

#incluir
#incluir
usando el espacio de nombres STD;

Este artículo explica los conceptos básicos de expresión regulares en C++.

Contenido del artículo

  • Fundamentos de expresión regulares
  • Patrón
  • Clases de personajes
  • Whitespaces coincidentes
  • El período (.) en el patrón
  • Repeticiones coincidentes
  • Alternancia coincidente
  • Coincidencia de inicio o final
  • Agrupamiento
  • ICASE y multiline regex_constants
  • Coincidir con todo el objetivo
  • El objeto Match_Results
  • Posición del partido
  • Buscar y reemplazar
  • Conclusión

Fundamentos de expresión regulares

Regular

Una cadena como "Aquí está mi hombre."Arriba está la secuencia de destino o cadena de destino o simplemente, Target. "Hombre", que fue buscado, es la expresión regular, o simplemente, regex.

Pareo

Se dice que la coincidencia ocurre cuando se encuentra la palabra o frase que se está buscando. Después de la coincidencia, puede realizarse un reemplazo. Por ejemplo, después de que "hombre" se encuentra arriba, puede ser reemplazado por "mujer".

Emparejamiento simple

El siguiente programa muestra cómo se combina la palabra "hombre".

#incluir
#incluir
usando el espacio de nombres STD;
int main ()

regex reg ("hombre");
if (regex_search ("Aquí está mi hombre.", reg))
cout << "matched" << endl;
demás
cout << "not matched" << endl;
regresar 0;

La función regex_search () devuelve verdaderas si hay una coincidencia y devuelve falso si no se produce una coincidencia. Aquí, la función toma dos argumentos: la primera es la cadena de destino, y la segunda es el objeto regex. La regex en sí es "hombre", en doble cotas. La primera declaración en la función main () forma el objeto regex. Regex es un tipo, y Reg es el objeto Regex. La salida del programa anterior se "coincide", ya que se ve "hombre" en la cadena de destino. Si no se viera "hombre" en el objetivo, regex_search () habría devuelto falso, y la salida habría sido "no coincidente".

La salida del siguiente código "no coincide":

regex reg ("hombre");
if (regex_search ("Aquí está mi fabricación.", reg))
cout << "matched" << endl;
demás
cout << "not matched" << endl;

No coincidente porque el "hombre" regex no se pudo encontrar en toda la cadena de destino ", aquí está mi fabricación."

Patrón

La expresión regular, "hombre" arriba, es muy simple. Los regexos generalmente no son tan simples. Las expresiones regulares tienen metacharacteres. Los metacharacteres son personajes con significados especiales. Un metacharacter es un personaje sobre personajes. C ++ Regex Metacharacters son:

^ $ \ . * + ? () [] |

Una regex, con o sin metacharacteres, es un patrón.

Clases de personajes

Corchetes

Un patrón puede tener caracteres dentro de los soportes cuadrados. Con esto, una posición particular en la cadena de destino coincidiría con cualquiera de los caracteres de los soportes cuadrados. Considere los siguientes objetivos:

"El gato está en la habitación."
"El bate está en la habitación."
"La rata está en la habitación."

El regex, [CBR] at coincidiría con CAT en el primer objetivo. Coincidiría con el bate en el segundo objetivo. Coincidiría con la rata en el tercer objetivo. Esto se debe a que, "gato" o "murciélago" o "rata" comienza con 'c' o 'b' o 'r'. El siguiente segmento de código ilustra esto:

regex reg ("[cbr] at");
if (regex_search ("El gato está en la habitación.", reg))
cout << "matched" << endl;
if (regex_search ("El murciélago está en la habitación.", reg))
cout << "matched" << endl;
if (regex_search ("La rata está en la habitación.", reg))
cout << "matched" << endl;

La salida es:

coincidente
coincidente
coincidente

Gama de personajes

La clase, [CBR] en el patrón [CBR], coincidiría con varios caracteres posibles en el objetivo. Coincidiría con 'c' o 'b' o 'r' en el objetivo. Si el objetivo no tiene ninguno de 'C' o 'B' o 'R', seguido de "AT", no habría partido.

Algunas posibilidades como 'C' o 'B' o 'R' existen en un rango. El rango de dígitos, 0 a 9 tiene 10 posibilidades, y el patrón para eso es [0-9]. El rango de alfabetos en minúsculas, A a Z, tiene 26 posibilidades, y el patrón para eso es [A-Z]. El rango de alfabetos en mayúsculas, A a Z, tiene 26 posibilidades, y el patrón para eso es [A-Z]. - no es oficialmente un metacharacter, pero dentro de los soportes cuadrados, indicaría un rango. Entonces, lo siguiente produce un partido:

if (regex_search ("id6id", regex ("[0-9]"))))
cout << "matched" << endl;

Observe cómo se ha construido el Regex como el segundo argumento. La coincidencia ocurre entre el dígito, 6 en el rango, 0 a 9, y el 6 en el objetivo, "id6id". El código anterior es equivalente a:

if (regex_search ("id6id", regex ("[0123456789]"))))
cout << "matched" << endl;

El siguiente código produce una coincidencia:

char str [] = "id6ie";
if (regex_search (str, regex ("[a-z]")))
cout << "matched" << endl;

Tenga en cuenta que el primer argumento aquí es una variable de cadena y no la cadena literal. El partido es entre 'I' en [A-Z] y 'I' en "Id6ie".

No olvides que un rango es una clase. Puede haber texto a la derecha del rango o a la izquierda del rango en el patrón. El siguiente código produce una coincidencia:

if (regex_search ("id2idpost-95222 -__ ddelink__294_3116034780"> es una id ", regex (" id [0-9] id "))))))
cout << "matched" << endl;

La coincidencia es entre "ID [0-9] ID" y "ID2ID". El resto de la cadena de destino, "es una identificación", no coincide en esta situación.

Como se usa en el sujeto de expresión regular (reglexes), la clase de palabras en realidad significa un conjunto. Es decir, uno de los personajes del set es coincidir.

Nota: El guión es un metacharacter solo dentro de los soportes cuadrados, lo que indica un rango. No es un metacharacter en el regex, fuera de los soportes cuadrados.

Negación

Se puede negar una clase que incluye un rango. Es decir, los no de los caracteres en el set (clase) deberían coincidir. Esto se indica con el ^ metacharacter al comienzo del patrón de clase, justo después del soporte cuadrado de apertura. Entonces, [^0-9] significa coincidir con el carácter en la posición apropiada en el objetivo, que no es ningún carácter en el rango, 0 a 9 inclusive. Entonces, el siguiente código no producirá una coincidencia:

if (regex_search ("0123456789101112", regex ("[^0-9]"))))
cout << "matched" << endl;
demás
cout << "not matched" << endl;

Se puede encontrar un dígito dentro del rango 0 a 9 en cualquiera de las posiciones de cadena de destino, "0123456789101112"; Entonces no hay ningún partido - Negación.

El siguiente código produce una coincidencia:

if (regex_search ("abcdefghij", regex ("[^0-9]"))))
cout << "matched" << endl;

No se pudo encontrar ningún dígito en el objetivo, "abcdefghij"; Entonces hay un partido.

[A-Z] es un rango afuera [^A-Z]. Y así [^a-z] es la negación de [a-z].

[A-Z] es un rango afuera [^A-Z]. Y así [^a-z] es la negación de [a-z].

Existen otras negaciones.

Whitespaces coincidentes

"o \ t o \ r o \ n o \ f es un carácter de espacio blanco. En el siguiente código, el regex, "\ n" coincide con 'n' en el objetivo:

if (regex_search ("de la línea uno.\ r \ nof línea dos.", regex (" \ n ")))
cout << "matched" << endl;

Coincidir con cualquier personaje de espacio blanco

El patrón o clase para que coincida con cualquier carácter de espacio en blanco es, [\ t \ r \ n \ f]. En el siguiente código, "se combina:

if (regex_search ("one dos", regex ("[\ t \ r \ n \ f]"))))
cout << "matched" << endl;

Hacer coincidir cualquier personaje que no sea blanco

El patrón o clase para que coincida con cualquier carácter de espacio no blanco es, [^ \ t \ r \ n \ f]. El siguiente código produce una coincidencia porque no hay espacio en blanco en el objetivo:

if (regex_search ("1234abcd", regex ("[^ \ t \ r \ n \ f]"))))
cout << "matched" << endl;

El período (.) en el patrón

El período (.) en el patrón coincide con cualquier carácter que incluya a sí mismo, excepto \ n, en el objetivo. Se produce una coincidencia en el siguiente código:

if (regex_search ("1234abcd", regex (".")))
cout << "matched" << endl;

No hay resultados coincidentes en el siguiente código porque el objetivo es "\ n".

if (regex_search ("\ n", regex (".")))
cout << "matched" << endl;
demás
cout << "not matched" << endl;

Nota: Dentro de una clase de caracteres con soportes cuadrados, el período no tiene un significado especial.

Repeticiones coincidentes

Un personaje o un grupo de caracteres puede ocurrir más de una vez dentro de la cadena de destino. Un patrón puede igualar esta repetición. Los metacharacteres, ?, *, +y se utilizan para que coincidan con la repetición en el objetivo. Si X es un carácter de interés en la cadena objetivo, entonces los metacharacteres tienen los siguientes significados:

x*: significa coincidir 'x' 0 o más veces, yo.mi., cualquier cantidad de veces
x+: significa coincidir 'x' 1 o más veces, yo.mi., al menos una vez
X? : significa coincidir 'x' 0 o 1 vez
x n,: significa coincidir con 'x' al menos n o más veces. Tenga en cuenta la coma.
x n: coincidir 'x' exactamente n veces
x n, m: coincidir con 'x' al menos n veces, pero no más que m veces.

Estos metacharacteres se llaman cuantificadores.

Ilustraciones

*

El * coincide con el carácter anterior o el grupo anterior, cero o más veces. "O*" coincide con 'o' en "perro" de la cadena objetivo. También coincide con "OO" en "Libro" y "Looking". La regex, "o*" coincide con "boooo" en "The Animal Booooed.". NOTA: "O*" coincide con "cavar", donde 'o' ocurre cero (o más) tiempo.

+

El + coincide con el carácter anterior o el grupo anterior, 1 o más veces. Contrastarlo con cero o más veces para *. Entonces el regex, "e+" coincide con 'e' en "comer", donde se produce 'e' una vez. "E+" también coincide con "ee" en "ovejas", donde 'e' ocurre más de una vez. Nota: "E+" no coincidirá con "cavar" porque en "cavar", 'e' no ocurre al menos una vez.

?

El ? coincide con el carácter anterior o el grupo anterior, 0 o 1 tiempo (y no más). Entonces, "E?"Coincide con" cavar "porque 'e' ocurre en" cavar ", cero tiempo. "mi?"Coinciden" establecidos "porque 'e' ocurre en" set ", una vez. Nota: "E?"Todavía coincide con" oveja "; Aunque hay dos 'e en "ovejas". Hay un matiz aquí, ver más tarde.

norte,

Esto coincide con al menos n repeticiones consecutivas de un carácter anterior o grupo anterior. Entonces, el Regex, "E 2," coincide con los dos 'e en el objetivo, "ovejas" y las tres' e en el objetivo "sheeep". "E 2," no coincide con "set", porque "set" solo tiene una 'e'.

norte

Esto coincide exactamente con las repeticiones consecutivas de un carácter anterior o grupo anterior. Entonces, la regex, "E 2" coincide con los dos 'e en el objetivo, "ovejas". "E 2" no coincide con "establecer" porque "set" tiene solo una 'e'. Bueno, "E 2" coincide con dos 'E en el objetivo, "Sheeep". Hay un matiz aquí, ver más tarde.

Nuevo Méjico

Esto coincide con varias repeticiones consecutivas de un carácter anterior o grupo anterior, desde n a M, inclusive. Entonces, "E 1,3" no coincide con nada en "Dig", que no tiene 'E'. Coincide con el 'e' en "set", los dos 'e en "ovejas", los tres' e en "sheeep" y tres 'e en "sheeeep". Hay un matiz en el último partido, ver más tarde.

Alternancia coincidente

Considere la siguiente cadena de destino en la computadora.

"La granja tiene cerdos de diferentes tamaños."

El programador puede querer saber si este objetivo tiene "cabra" o "conejo" o "cerdo". El código sería el siguiente:

char str [] = "La granja tiene cerdos de diferentes tamaños.";
if (regex_search (str, regex ("cabra | conejo | cerdo"))))
cout << "matched" << endl;
demás
cout << "not matched" << endl;

El código produce una coincidencia. Tenga en cuenta el uso del carácter de alternancia, |. Puede haber dos, tres, cuatro y más opciones. C ++ primero intentará que coincida con la primera alternativa, "Goat", en cada posición de personaje en la cadena de destino. Si no tiene éxito con la "cabra", intenta la próxima alternativa, "conejo". Si no tiene éxito con "Rabbit", intenta la próxima alternativa, "Pig". Si "Pig" falla, entonces C ++ pasa a la siguiente posición en el objetivo y comienza con la primera alternativa nuevamente.

En el código anterior, "Pig" coincide.

Coincidencia de inicio o final

Comienzo


Si ^ está al comienzo de la regex, entonces el texto inicial de la cadena de destino puede coincidir con el regex. En el siguiente código, el inicio del objetivo es "ABC", que coincide:

if (regex_search ("ABC y def", regex ("^ABC"))))
cout << "matched" << endl;

No se produce una coincidencia en el siguiente código:

if (regex_search ("Sí, ABC y def", regex ("^ABC"))))
cout << "matched" << endl;
demás
cout << "not matched" << endl;

Aquí, "ABC" no está al comienzo del objetivo.

NOTA: El carácter circunflejo, '^', es un metacharacter al comienzo de la regex, coincidiendo con el inicio de la cadena de destino. Sigue siendo un metacharacter al comienzo de la clase de caracteres, donde niega la clase.

Fin

Si $ está al final de la regex, entonces el texto final de la cadena de destino puede coincidir con el Regex. En el siguiente código, el final del objetivo es "XYZ", que coincide:

if (regex_search ("UVW y xyz", regex ("xyz $"))))
cout << "matched" << endl;

No se produce una coincidencia en el siguiente código:

if (regex_search ("UVW y xyz final", regex ("xyz $"))))
cout << "matched" << endl;
demás
cout << "not matched" << endl;

Aquí, "xyz" no está al final del objetivo.

Agrupamiento

Los paréntesis se pueden usar para agrupar caracteres en un patrón. Considere la siguiente regex:

"Un concierto (pianista)"

El grupo aquí es "pianista" rodeado por los metacharacteres (y). En realidad es un subgrupo, mientras que "un concierto (pianista)" es todo el grupo. Considera lo siguiente:

"El (pianista es bueno)"

Aquí, el subgrupo o la substing es: "El pianista es bueno".

Subcontratos con partes comunes

Un contador es una persona que cuida los libros. Imagina una biblioteca con una contadora y estantería. Suponga que una de las siguientes cadenas de destino está en la computadora:

"La biblioteca tiene una estantería admirada.";
"Aquí está el contador.";
"El contable trabaja con la estantería.";

Suponga que el interés del programador no es saber cuál de estas oraciones está en la computadora. Aún así, su interés es saber si "estantería" o "contable" está presente en cualquier cadena objetivo que esté en la computadora. En este caso, su regex puede ser:

"Bookshelf | contable."

Usando alternancia.

Observe que el "libro", que es común a ambas palabras, se ha escrito dos veces, en las dos palabras del patrón. Para evitar escribir "libro" dos veces, el Regex estaría mejor escrito como:

"Libro (estante | Guardián)"

Aquí, el grupo, "estante | guardián", la alternancia de metacharacter todavía se ha utilizado, pero no por dos palabras largas. Se ha utilizado para las dos partes finales de las dos palabras largas. C ++ trata a un grupo como una entidad. Entonces, C ++ buscará "estante" o "guardián" que viene inmediatamente después de "libro". La salida del siguiente código está "coincidente":

char str [] = "La biblioteca tiene una estantería admirada.";
if (regex_search (str, regex ("book (estante | guardián)"))))
cout << "matched" << endl;

"Librería" y no "Contabilidad" se han combinado.

ICASE y multiline regex_constants

Icase

La coincidencia es sensible a la caja por defecto. Sin embargo, se puede hacer insensible. Para lograr esto, use la constante regex :: icase, como en el siguiente código:

if (regex_search ("comentarios", regex ("feed", regex :: icase))))
cout << "matched" << endl;

La salida está "coincidente". Entonces, "retroalimentación" con 'f' en mayúsculas se ha combinado con "feed" con minúscula 'f'. "Regex :: icase" se ha convertido en el segundo argumento del constructor regex (). Sin eso, la declaración no produciría una coincidencia.

Multilínea

Considere el siguiente código:

char str [] = "línea 1 \ nline 2 \ nline 3";
if (regex_search (str, regex ("^.ps
cout << "matched" << endl;
demás
cout << "not matched" << endl;

La salida "no coincide". El regex, "^.*$ ", Coincide con la cadena de destino desde su comienzo hasta su fin. ".*”Significa cualquier personaje excepto \ n, cero o más veces. Entonces, debido a los personajes de Newline (\ n) en el objetivo, no hubo coincidencia.

El objetivo es una cadena multilínea. Para poder '.'Para que coincida con el personaje de Newline, se debe hacer el constante "Regex :: Multiline", el segundo argumento de la construcción regex (). El siguiente código ilustra esto:

char str [] = "línea 1 \ nline 2 \ nline 3";
if (regex_search (str, regex ("^.*$ ", regex :: multiline)))
cout << "matched" << endl;
demás
cout << "not matched" << endl;

Coincidir con toda la cadena de destino

Para que coincida con la cadena de destino completa, que no tiene el carácter nuevo (\ n), se puede usar la función regex_match (). Esta función es diferente de regex_search (). El siguiente código ilustra esto:

char str [] = "primer segundo tercio";
if (regex_match (str, regex (".*segundo.*")))
cout << "matched" << endl;

Hay un partido aquí. Sin embargo, tenga en cuenta que la regla coincide con la cadena de destino completa, y la cadena de destino no tiene ninguna '\ n'.

El objeto Match_Results

La función regex_search () puede llevar un argumento entre el destino y el objeto regex. Este argumento es el objeto Match_Results. Toda la cadena coincidente (parte) y las sub-strings coincidentes se pueden conocer con ella. Este objeto es una matriz especial con métodos. El tipo de objeto Match_Results es cmatch (para literales de cadena).

Obtener partidos

Considere el siguiente código:

char str [] = "La mujer que estabas buscando!";
cmatch m;
if (regex_search (str, m, regex ("w.metro.norte")))
cout << m[0] << endl;

La cadena objetivo tiene la palabra "mujer". La salida es "mujer", que corresponde a la regex, "w.metro.norte". En el índice cero, la matriz especial posee el único partido, que es "mujer".

Con las opciones de clase, solo la primera subtracción que se encuentra en el objetivo, se envía a la matriz especial. El siguiente código ilustra esto:

cmatch m;
if (regex_search ("la rata, el gato, el murciélago!", m, regex (" [bcr] at ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

La salida es "rata" del índice cero. m [1] y m [2] están vacíos.

Con alternativas, solo la primera subtracción que se encuentra en el objetivo, se envía a la matriz especial. El siguiente código ilustra esto:

if (regex_search ("El conejo, la cabra, el cerdo!", m, regex (" cabra | conejo | cerdo ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;

La salida es "conejo" del índice cero. m [1] y m [2] están vacíos.

Agrupación

Cuando los grupos están involucrados, el patrón completo coincide, entra en la celda cero de la matriz especial. La siguiente sub-string encontrada va a la celda 1; La subtracción siguiente, entra en la celda 2; etcétera. El siguiente código ilustra esto:

if (regex_search ("Mejor librero hoy!", m, regex (" libro ((sel) (ler)) ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;

La salida es:

librero
vendedor
sel
ler

Tenga en cuenta que el grupo (vendedor) viene antes del grupo (SEL).

Posición del partido

Se puede conocer la posición de coincidencia para cada subtracción en la matriz Cmatch. El recuento comienza desde el primer carácter de la cadena objetivo, en la posición cero. El siguiente código ilustra esto:

cmatch m;
if (regex_search ("Mejor librero hoy!", m, regex (" libro ((sel) (ler)) ")))
cout << m[0] << "->" << m.position(0) << endl;
cout << m[1] << "->" << m.position(1) << endl;
cout << m[2] << "->" << m.position(2) << endl;
cout << m[3] << "->" << m.position(3) << endl;

Tenga en cuenta el uso de la propiedad de posición, con el índice de celda, como argumento. La salida es:

Librería-> 5
vendedor-> 9
Sel-> 9
ler-> 12

Buscar y reemplazar

Una nueva palabra o frase puede reemplazar la coincidencia. La función regex_replace () se usa para esta. Sin embargo, esta vez, la cadena donde ocurre el reemplazo es el objeto de cadena, no la cadena literal. Entonces, la biblioteca de cadenas debe incluirse en el programa. Ilustración:

#incluir
#incluir
#incluir
usando el espacio de nombres STD;
int main ()

cadena str = "Aquí viene mi hombre. Ahí va tu hombre.";
String Newstr = regex_replace (str, regex ("hombre"), "mujer");
cout << newStr << endl;
regresar 0;

La función regex_replace (), como se codifica aquí, reemplaza todas las coincidencias. El primer argumento de la función es el objetivo, el segundo es el objeto regex, y el tercero es la cadena de reemplazo. La función devuelve una nueva cadena, que es el objetivo pero tiene el reemplazo. La salida es:

"Aquí viene mi mujer. Ahí va tu mujer."

Conclusión

La expresión regular usa patrones para que coincidan con sustros en la cadena de secuencia de destino. Los patrones tienen metacharacteres. Funciones de uso común para expresiones regulares C ++, son: regex_search (), regex_match () y regex_replace (). Un regex es un patrón en quotas dobles. Sin embargo, estas funciones toman el objeto regex como argumento y no solo el regex. El registro debe convertirse en un objeto regex antes de que estas funciones puedan usarlo.