Esta string pode estar dentro do computador, e o usuário pode querer saber se ela contém a palavra “man”. Se tiver a palavra homem, ele pode querer mudar a palavra “homem” para “mulher”; de modo que a string deve ser:
"Aqui está minha mulher."Existem muitos outros desejos como esses do usuário do computador; alguns são complexos. Expressão regular, abreviado, regex, é o assunto para lidar com esses problemas pelo computador. C ++ vem com uma biblioteca chamada regex. Portanto, um programa C ++ para lidar com regex deve começar com:
#incluir#incluir
usando namespace std;
Este artigo explica noções básicas de expressões regulares em C++.
Conteúdo do Artigo
- Fundamentos da expressão regular
- Padrão
- Classes de personagens
- Espaços em branco correspondentes
- O período (.) no padrão
- Repetições correspondentes
- Alternância de correspondência
- Início ou Fim da Correspondência
- Agrupamento
- As constantes icase e regex_constants multilinhas
- Combinando o alvo inteiro
- O objeto match_results
- Posição da partida
- Pesquisar e substituir
- Conclusão
Fundamentos da expressão regular
Regex
Uma string como “Aqui está meu homem."Acima é a sequência alvo ou string alvo ou simplesmente, alvo. “Man”, que foi pesquisado, é a expressão regular, ou simplesmente regex.
Coincidindo
Diz-se que a correspondência ocorre quando a palavra ou frase que está sendo pesquisada é localizada. Após a correspondência, uma substituição pode ocorrer. Por exemplo, depois que "homem" for localizado acima, ele pode ser substituído por "mulher".
Correspondência Simples
O programa a seguir mostra como a palavra "homem" é combinada.
#incluir#incluir
usando namespace std;
int main ()
regex reg ("homem");
if (regex_search ("Aqui está o meu homem.", reg))
cout << "matched" << endl;
senão
cout << "not matched" << endl;
return 0;
A função regex_search () retorna verdadeiro se houver uma correspondência e retorna falso se não ocorrer nenhuma correspondência. Aqui, a função leva dois argumentos: o primeiro é a string de destino e o segundo é o objeto regex. A própria regex é "man", entre aspas duplas. A primeira instrução na função main () forma o objeto regex. Regex é um tipo e reg é o objeto regex. A saída do programa acima é "combinada", pois "man" é visto na string de destino. Se "man" não fosse visto no destino, regex_search () teria retornado falso e a saída teria sido "incompatível".
A saída do seguinte código é “não correspondente”:
regex reg ("homem");if (regex_search ("Aqui está minha criação.", reg))
cout << "matched" << endl;
senão
cout << "not matched" << endl;
Não correspondeu porque a regex "man" não pôde ser encontrada em toda a string de destino, "Aqui está minha criação."
Padrão
A expressão regular, "homem" acima, é muito simples. Regexes geralmente não são tão simples. Expressões regulares têm metacaracteres. Metacaracteres são caracteres com significados especiais. Um metacaractere é um personagem sobre personagens. Os metacaracteres C ++ regex são:
^ $ \ . * + ? () [] |Um regex, com ou sem metacaracteres, é um padrão.
Classes de personagens
Colchetes
Um padrão pode ter caracteres entre colchetes. Com isso, uma posição particular na string alvo corresponderia a qualquer um dos caracteres dos colchetes. Considere os seguintes alvos:
"O gato esta na sala.""O morcego está na sala."
"O rato está na sala."
A regex, [cbr] em corresponderia a cat no primeiro destino. Seria igualar o morcego no segundo alvo. Corresponderia ao rato no terceiro alvo. Isso ocorre porque "gato" ou "morcego" ou "rato" começa com 'c' ou 'b' ou 'r'. O seguinte segmento de código ilustra isso:
regex reg ("[cbr] em");if (regex_search ("O gato está na sala.", reg))
cout << "matched" << endl;
if (regex_search ("O morcego está na sala.", reg))
cout << "matched" << endl;
if (regex_search ("O rato está na sala.", reg))
cout << "matched" << endl;
O resultado é:
coincidecoincide
coincide
Gama de personagens
A classe, [cbr] no padrão [cbr], corresponderia a vários caracteres possíveis no destino. Corresponderia a 'c' ou 'b' ou 'r' no alvo. Se o alvo não tiver nenhum 'c' ou 'b' ou 'r', seguido por "em", não haveria correspondência.
Algumas possibilidades como 'c' ou 'b' ou 'r' existem em um intervalo. O intervalo de dígitos, de 0 a 9, tem 10 possibilidades, e o padrão para isso é [0-9]. O intervalo de letras minúsculas, de a a z, tem 26 possibilidades, e o padrão para isso é [a-z]. A faixa de letras maiúsculas, de A a Z, tem 26 possibilidades, e o padrão para isso é [A-Z]. - não é oficialmente um metacaractere, mas entre colchetes, indica um intervalo. Portanto, o seguinte produz uma correspondência:
if (regex_search ("ID6id", regex ("[0-9]")))cout << "matched" << endl;
Observe como a regex foi construída como o segundo argumento. A correspondência ocorre entre o dígito, 6 no intervalo, 0 a 9, e o 6 no destino, “ID6id”. O código acima é equivalente a:
if (regex_search ("ID6id", regex ("[0123456789]")))cout << "matched" << endl;
O código a seguir produz uma correspondência:
char str [] = "ID6iE";if (regex_search (str, regex ("[a-z]")))
cout << "matched" << endl;
Observe que o primeiro argumento aqui é uma variável de string e não o literal de string. A correspondência é entre 'i' em [a-z] e 'i' em “ID6iE”.
Não se esqueça que um intervalo é uma classe. Pode haver texto à direita do intervalo ou à esquerda do intervalo no padrão. O código a seguir produz uma correspondência:
if (regex_search ("ID2id é um ID ", regex (" ID [0-9] id ")))cout << "matched" << endl;
A correspondência é entre “ID [0-9] id” e “ID2id”. O resto da string de destino, "é um ID", não é correspondido nesta situação.
Conforme usado no assunto da expressão regular (regexes), a palavra classe na verdade significa um conjunto. Ou seja, um dos personagens do conjunto deve corresponder.
Observação: o hífen - é um metacaractere apenas entre colchetes, indicando um intervalo. Não é um metacaractere no regex, fora dos colchetes.
Negação
Uma classe incluindo um intervalo pode ser negada. Ou seja, nenhum dos personagens do conjunto (classe) deve corresponder. Isso é indicado com o metacaractere ^ no início do padrão de classe, logo após o colchete de abertura. Portanto, [^ 0-9] significa combinar o caractere na posição apropriada no destino, que não é nenhum caractere no intervalo, de 0 a 9, inclusive. Portanto, o código a seguir não produzirá uma correspondência:
if (regex_search ("0123456789101112", regex ("[^ 0-9]")))cout << "matched" << endl;
senão
cout << "not matched" << endl;
Um dígito no intervalo de 0 a 9 pode ser encontrado em qualquer uma das posições da string de destino, “0123456789101112,”; então não há correspondência - negação.
O código a seguir produz uma correspondência:
if (regex_search ("ABCDEFGHIJ", regex ("[^ 0-9]")))cout << "matched" << endl;
Nenhum dígito foi encontrado no destino, “ABCDEFGHIJ,”; então há uma correspondência.
[a-z] é um intervalo fora de [^ a-z]. E então [^ a-z] é a negação de [a-z].
[A-Z] é um intervalo fora de [^ A-Z]. E então [^ A-Z] é a negação de [A-Z].
Existem outras negações.
Espaços em branco correspondentes
"ou \ t ou \ r ou \ n ou \ f é um caractere de espaço em branco. No código a seguir, o regex, “\ n” corresponde a '\ n' no destino:
if (regex_search ("Da linha um.\ r \ nDa linha dois.", regex (" \ n ")))cout << "matched" << endl;
Combinando qualquer caractere de espaço em branco
O padrão ou classe para corresponder a qualquer caractere de espaço em branco é, [\ t \ r \ n \ f]. No código a seguir, "é correspondido:
if (regex_search ("um dois", regex ("[\ t \ r \ n \ f]")))cout << "matched" << endl;
Combinando qualquer caractere sem espaço em branco
O padrão ou classe para corresponder a qualquer caractere diferente de espaço em branco é, [^ \ t \ r \ n \ f]. O código a seguir produz uma correspondência porque não há nenhum espaço em branco no destino:
if (regex_search ("1234abcd", regex ("[^ \ t \ r \ n \ f]")))cout << "matched" << endl;
O período (.) no padrão
O período (.) no padrão corresponde a qualquer caractere incluindo ele mesmo, exceto \ n, no destino. Uma correspondência é produzida no seguinte código:
if (regex_search ("1234abcd", regex (".")))cout << "matched" << endl;
Nenhum resultado correspondente no código a seguir porque o destino é “\ n”.
if (regex_search ("\ n", regex (".")))cout << "matched" << endl;
senão
cout << "not matched" << endl;
Nota: dentro de uma classe de caractere com colchetes, o ponto não tem nenhum significado especial.
Repetições correspondentes
Um caractere ou grupo de caracteres pode ocorrer mais de uma vez dentro da string de destino. Um padrão pode corresponder a esta repetição. Os metacaracteres, ?, *, + e são usados para combinar a repetição no alvo. Se x é um caractere de interesse na string de destino, os metacaracteres têm os seguintes significados:
x *: significa corresponder a 'x' 0 ou mais vezes, i.e., qualquer número de vezesx +: significa corresponder a 'x' 1 ou mais vezes, i.e., pelo menos uma vez
x? : significa corresponder 'x' 0 ou 1 vez
x n,: significa corresponder a 'x' pelo menos n ou mais vezes. Observe a vírgula.
x n: corresponde a 'x' exatamente n vezes
x n, m: corresponde a 'x' pelo menos n vezes, mas não mais do que m vezes.
Esses metacaracteres são chamados de quantificadores.
Ilustrações
*
O * corresponde ao caractere anterior ou ao grupo anterior, nenhuma ou mais vezes. “O *” corresponde a 'o' em “cão” da string alvo. Também corresponde a “oo” em “livro” e “procurando”. O regex, “o *” corresponde a “boooo” em “The animal booooed.”. Nota: “o *” corresponde a “dig”, onde 'o' ocorre zero (ou mais).
+
O + corresponde ao caractere anterior ou ao grupo anterior, 1 ou mais vezes. Compare-o com zero ou mais vezes para *. Portanto, a regex, “e +” corresponde a 'e' em “comer”, onde 'e' ocorre uma vez. “E +” também corresponde a “ee” em “ovelha”, onde 'e' ocorre mais de uma vez. Nota: “e +” não corresponderá a “dig” porque em “dig”, 'e' não ocorre pelo menos uma vez.
?
O ? corresponde ao caractere anterior ou grupo anterior, 0 ou 1 vez (e não mais). Então, “e?”Corresponde a“ dig ”porque 'e' ocorre em“ dig ”, tempo zero. “E?”Corresponde a“ set ”porque 'e' ocorre em“ set ”, uma vez. Nota: “e?”Ainda corresponde a“ ovelha ”; embora haja dois 'e's em "ovelhas". Há uma nuance aqui - veja mais tarde.
n,
Corresponde a pelo menos n repetições consecutivas de um caractere anterior ou grupo anterior. Portanto, a regex, "e 2," corresponde aos dois 'e's no destino, "ovelha", e os três' e's no destino "sheeep". “E 2,” não corresponde a “set”, porque “set” tem apenas um 'e'.
n
Corresponde exatamente a n repetições consecutivas de um caractere anterior ou grupo anterior. Portanto, a regex, “e 2” corresponde aos dois 'e's no destino, “ovelha”. “E 2” não corresponde a “set” porque “set” tem apenas um 'e'. Bem, “e 2” corresponde a dois 'e's no alvo, “sheeep”. Há uma nuance aqui - veja mais tarde.
n, m
Corresponde a várias repetições consecutivas de um caractere anterior ou grupo anterior, em qualquer lugar de n a m, inclusive. Portanto, “e 1,3” não corresponde a nada em “dig”, que não tem 'e'. Corresponde ao um 'e' em “conjunto”, os dois 'e's em “ovelha”, os três' e's em “sheeep” e três 'e's em “sheeeep”. Há uma nuance na última partida - veja mais tarde.
Alternância de correspondência
Considere a seguinte string de destino no computador.
“A fazenda tem porcos de diferentes tamanhos.”
O programador pode querer saber se este alvo tem “cabra” ou “coelho” ou “porco”. O código seria o seguinte:
char str [] = "A fazenda tem porcos de tamanhos diferentes.";if (regex_search (str, regex ("cabra | coelho | porco")))
cout << "matched" << endl;
senão
cout << "not matched" << endl;
O código produz uma correspondência. Observe o uso do caractere de alternância, |. Pode haver duas, três, quatro e mais opções. C ++ tentará primeiro corresponder à primeira alternativa, "cabra", em cada posição de caractere na string de destino. Se não tiver sucesso com “cabra”, ele tenta a próxima alternativa, “coelho”. Se não tiver sucesso com “coelho”, ele tenta a próxima alternativa, “porco”. Se “pig” falhar, então C ++ passa para a próxima posição no alvo e começa com a primeira alternativa novamente.
No código acima, “pig” é correspondido.
Início ou Fim da Correspondência
Começo
Se ^ estiver no início da regex, o texto inicial da string de destino pode ser correspondido pela regex. No código a seguir, o início do destino é “abc”, que corresponde a:
cout << "matched" << endl;
Nenhuma correspondência ocorre no seguinte código:
if (regex_search ("Sim, abc e def", regex ("^ abc")))cout << "matched" << endl;
senão
cout << "not matched" << endl;
Aqui, “abc” não está no início do destino.
Observação: o caractere circunflexo, '^', é um metacaractere no início da regex, correspondendo ao início da string de destino. Ainda é um metacaractere no início da classe de personagem, onde nega a classe.
Fim
Se $ estiver no final da regex, então o texto final da string de destino pode ser correspondido pela regex. No código a seguir, o final do destino é “xyz”, que corresponde a:
if (regex_search ("uvw e xyz", regex ("xyz $")))cout << "matched" << endl;
Nenhuma correspondência ocorre no seguinte código:
if (regex_search ("uvw e xyz final", regex ("xyz $")))cout << "matched" << endl;
senão
cout << "not matched" << endl;
Aqui, “xyz” não está no final do alvo.
Agrupamento
Os parênteses podem ser usados para agrupar caracteres em um padrão. Considere o seguinte regex:
"um concerto (pianista)"O grupo aqui é “pianista” rodeado pelos metacaracteres (e). Na verdade, é um subgrupo, enquanto "um concerto (pianista)" é todo o grupo. Considere o seguinte:
"O (pianista é bom)"Aqui, o subgrupo ou subcadeia é “pianist is good”.
Sub-strings com partes comuns
Um contador é uma pessoa que cuida de livros. Imagine uma biblioteca com guarda-livros e estante. Suponha que uma das seguintes strings de destino esteja no computador:
“A biblioteca tem uma estante que é admirada.";"Aqui está o contador.";
“O contador trabalha com a estante.";
Suponha que o interesse do programador não seja saber qual dessas frases está no computador. Ainda assim, seu interesse é saber se "estante" ou "guarda-livros" está presente em qualquer string de destino no computador. Nesse caso, sua regex pode ser:
"estante | contador."Usando alternância.
Observe que "livro", que é comum a ambas as palavras, foi digitado duas vezes, nas duas palavras do padrão. Para evitar digitar “livro” duas vezes, o regex seria melhor escrito como:
"livro (estante | guardião)"Aqui, o grupo, “shelf | keeper” O metacaractere de alternância ainda foi usado, mas não por duas palavras longas. Foi usado para as duas partes finais das duas palavras longas. C ++ trata um grupo como uma entidade. Então, C ++ irá procurar por “prateleira” ou “guardião” que vem imediatamente após “livro”. A saída do seguinte código é “correspondida”:
char str [] = "A biblioteca tem uma estante que é admirada.";if (regex_search (str, regex ("book (shelf | keeper)")))
cout << "matched" << endl;
“Estante” e não “guarda-livros” foram combinados.
As constantes icase e regex_constants multilinhas
icase
A correspondência diferencia maiúsculas de minúsculas por padrão. No entanto, pode ser indiferente a maiúsculas. Para fazer isso, use a constante regex :: icase, como no código a seguir:
if (regex_search ("Feedback", regex ("feed", regex :: icase)))cout << "matched" << endl;
A saída é "combinada". Portanto, “Feedback” com 'F' maiúsculo foi correspondido por “feed” com 'f' minúsculo. “Regex :: icase” tornou-se o segundo argumento do construtor regex (). Sem isso, a declaração não produziria uma correspondência.
Multilinha
Considere o seguinte código:
char str [] = "linha 1 \ nlinha 2 \ nlinha 3";if (regex_search (str, regex ("^.* $ ")))
cout << "matched" << endl;
senão
cout << "not matched" << endl;
A saída é “não combinada”. O regex, “^.* $, ”Corresponde à string de destino do início ao fim. “.* ”Significa qualquer caractere, exceto \ n, zero ou mais vezes. Então, por causa dos caracteres de nova linha (\ n) no destino, não houve correspondência.
O alvo é uma string multilinha. Em ordem para '.'para corresponder ao caractere de nova linha, a constante “regex :: multiline” deve ser feita, o segundo argumento da construção regex (). O código a seguir ilustra isso:
char str [] = "linha 1 \ nlinha 2 \ nlinha 3";if (regex_search (str, regex ("^.* $ ", regex :: multiline)))
cout << "matched" << endl;
senão
cout << "not matched" << endl;
Correspondência de toda a string de destino
Para corresponder a toda a string de destino, que não tem o caractere de nova linha (\ n), a função regex_match () pode ser usada. Esta função é diferente de regex_search (). O código a seguir ilustra isso:
char str [] = "primeiro segundo terço";if (regex_match (str, regex (".*segundo.* ")))
cout << "matched" << endl;
Há uma correspondência aqui. No entanto, observe que a regex corresponde a toda a string de destino, e a string de destino não tem nenhum '\ n'.
O objeto match_results
A função regex_search () pode receber um argumento entre o destino e o objeto regex. Este argumento é o objeto match_results. Toda a string combinada (parte) e as sub-strings combinadas podem ser conhecidas com ela. Este objeto é um array especial com métodos. O tipo de objeto match_results é cmatch (para literais de string).
Obtenção de fósforos
Considere o seguinte código:
char str [] = "A mulher que você estava procurando!";cmatch m;
if (regex_search (str, m, regex ("w.m.n ")))
cout << m[0] << endl;
A string de destino contém a palavra "mulher". A saída é “mulher ', que corresponde ao regex,“ w.m.n ”. No índice zero, a matriz especial contém a única correspondência, que é "mulher".
Com as opções de classe, apenas a primeira sub-string encontrada no destino é enviada para a matriz especial. O código a seguir ilustra isso:
cmatch m;if (regex_search ("O rato, o gato, o morcego!", m, regex (" [bcr] at ")))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
A saída é "rato" do índice zero. m [1] e m [2] estão vazios.
Com alternativas, apenas a primeira subcadeia encontrada no destino, é enviada para a matriz especial. O código a seguir ilustra isso:
if (regex_search ("O coelho, a cabra, o porco!", m, regex (" cabra | coelho | porco ")))cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
A saída é "coelho" do índice zero. m [1] e m [2] estão vazios.
Agrupamentos
Quando os grupos estão envolvidos, o padrão completo combinado vai para a célula zero da matriz especial. A próxima subcadeia encontrada vai para a célula 1; a subsequente seqüência de caracteres, vai para a célula 2; e assim por diante. O código a seguir ilustra isso:
if (regex_search ("Melhor livreiro hoje!", m, regex (" book ((sel) (ler)) ")))cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;
O resultado é:
livreirovendedor
sel
ler
Observe que o grupo (vendedor) vem antes do grupo (sel).
Posição da partida
A posição de correspondência para cada substring na matriz cmatch pode ser conhecida. A contagem começa a partir do primeiro caractere da string alvo, na posição zero. O código a seguir ilustra isso:
cmatch m;if (regex_search ("Melhor livreiro hoje!", m, regex (" book ((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;
Observe o uso da propriedade position, com o índice da célula, como um argumento. O resultado é:
livreiro-> 5vendedor-> 9
sel-> 9
ler-> 12
Pesquisar e substituir
Uma nova palavra ou frase pode substituir a correspondência. A função regex_replace () é usada para isso. No entanto, desta vez, a string onde ocorre a substituição é o objeto string, não o literal da string. Portanto, a biblioteca de strings deve ser incluída no programa. Ilustração:
#incluir#incluir
#incluir
usando namespace std;
int main ()
string str = "Aqui, vem meu homem. Lá vai seu homem.";
string newStr = regex_replace (str, regex ("homem"), "mulher");
cout << newStr << endl;
return 0;
A função regex_replace (), conforme codificada aqui, substitui todas as correspondências. O primeiro argumento da função é o destino, o segundo é o objeto regex e o terceiro é a string de substituição. A função retorna uma nova string, que é o destino, mas tendo a substituição. O resultado é:
“Aí vem minha mulher. Lá vai sua mulher.”
Conclusão
A expressão regular usa padrões para combinar substrings na string de sequência de destino. Os padrões têm metacaracteres. Funções comumente usadas para expressões regulares C ++, são: regex_search (), regex_match () e regex_replace (). Um regex é um padrão entre aspas duplas. No entanto, essas funções tomam o objeto regex como um argumento e não apenas o regex. O regex deve ser transformado em um objeto regex antes que essas funções possam usá-lo.