Expressão regular básica em C ++

Expressão regular básica em C ++
Considere a seguinte frase nas citações: "Aqui está meu homem."

Essa string pode estar dentro do computador, e o usuário pode querer saber se tem a palavra "cara". Se tiver a palavra homem, ele pode querer mudar a palavra "homem" para "mulher"; para que a string deve ler:

"Aqui está minha mulher."

Existem muitos outros desejos como esses do usuário do computador; Alguns são complexos. Expressão regular, abreviada, Regex, é objeto de 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 o básico da expressão regular em C++.

Conteúdo do artigo

  • Fundamentos regulares da expressão
  • Padrão
  • Classes de personagens
  • Combinando espaços de branco
  • O período (.) no padrão
  • Repetições correspondentes
  • Alternância correspondente
  • Combinando ou fim
  • Agrupamento
  • A ICASE e multiline regex_constants
  • Combinando todo o alvo
  • O objeto Match_Results
  • Posição da partida
  • Pesquise e substitua
  • Conclusão

Fundamentos regulares da expressão

Regex

Uma string como “Aqui está meu homem.”Acima está a sequência de destino ou string de destino ou simplesmente, alvo. "Homem", 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 está localizada. Após a correspondência, uma substituição pode ocorrer. Por exemplo, depois que o "homem" está localizado acima, ele pode ser substituído por "mulher".

Correspondência simples

O programa a seguir mostra como a palavra "homem" é comparada.

#incluir
#incluir
usando namespace std;
int main ()

Regex Reg ("Man");
if (regex_search ("Aqui está meu homem.", reg))
cout << "matched" << endl;
outro
cout << "not matched" << endl;
retornar 0;

A função regex_search () retorna true se houver uma correspondência e retornar false se não ocorrer correspondência. Aqui, a função leva dois argumentos: a primeira é a sequência de destino, e a segunda é o objeto Regex. O regex em si é "homem", em duas citações. A primeira declaração na função Main () forma o objeto regex. Regex é um tipo, e Reg é o objeto regex. A saída do programa acima é "correspondente", pois "Man" é visto na string de destino. Se "Man" não fosse visto no alvo, regex_search () teria retornado falso, e a saída teria sido "não correspondente".

A saída do código a seguir é "não correspondente":

Regex Reg ("Man");
if (regex_search ("aqui está minha criação.", reg))
cout << "matched" << endl;
outro
cout << "not matched" << endl;

Não correspondido porque o regex "homem" não pôde ser encontrado em toda a string alvo ", aqui está a 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 metacaracters. Metacharacters são personagens com significados especiais. Um Metacharacter é um personagem sobre personagens. C ++ Regex Metacharacters são:

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

Um regex, com ou sem metacaracters, é um padrão.

Classes de personagens

Suportes quadrados

Um padrão pode ter caracteres entre colchetes. Com isso, uma posição específica na sequência de destino corresponderia a qualquer um dos personagens dos colchetes quadrados. Considere os seguintes metas:

"O gato está na sala."
"O bastão está na sala."
"O rato está na sala."

O regex, [CBR] em corresponder ao CAT no primeiro alvo. Isso corresponderia ao bastão no segundo alvo. Combinaria com 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 o seguinte:

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;

A saída é:

coincide
coincide
coincide

Gama de caracteres

A classe, [CBR] no padrão [CBR], corresponderia a vários personagens possíveis no alvo. Ele corresponderia a 'c' ou 'b' ou 'r' no alvo. Se o alvo não tiver nada de 'c' ou 'b' ou 'r', seguido de "at", não haveria correspondência.

Algumas possibilidades como 'c' ou 'b' ou 'r' existem em um intervalo. A gama de dígitos, 0 a 9 tem 10 possibilidades, e o padrão para isso é [0-9]. A gama de alfabetos minúsculos, A a Z, tem 26 possibilidades, e o padrão para isso é [a-z]. A gama de alfabetos maiúsculos, a a z, tem 26 possibilidades, e o padrão para isso é [a-z]. - não é oficialmente um Metacharacter, mas entre colchetes, indicaria um intervalo. Então, o seguinte produz uma partida:

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

Observe como o regex foi construído como o segundo argumento. A partida ocorre entre o dígito, 6 no intervalo, 0 a 9, e o 6 no alvo, “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 a string literal. A partida é entre 'i' em [a-z] e 'i' em “id6ie”.

Não se esqueça que um intervalo é uma classe. Pode haver texto à direita do alcance ou à esquerda do alcance no padrão. O código a seguir produz uma correspondência:

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

A partida é entre "id [0-9] id" e "id2id". O restante da sequência de destino, "é um id", não é comparado nesta situação.

Conforme usado no assunto da expressão regular (regexes), a classe Word realmente significa um conjunto. Isto é, um dos personagens do set é combinar.

Nota: O hífen - é um metacaracter apenas entre colchetes, indicando um intervalo. Não é um metacaracter no regex, fora dos colchetes quadrados.

Negação

Uma aula incluindo um intervalo pode ser negada. Ou seja, não dos personagens do set (classe) devem corresponder. Isso é indicado com o ^ Metacharacter no início do padrão de classe, logo após o suporte quadrado de abertura. Então, [^0-9] significa combinar o personagem na posição apropriada no alvo, o que não é nenhum caractere no intervalo, 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;
outro
cout << "not matched" << endl;

Um dígito dentro do intervalo de 0 a 9 pode ser encontrado em qualquer uma das posições de sequência de destino, “0123456789101112”; Portanto, 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 alvo, "abcdefghij"; Então há uma partida.

[A-Z] é uma faixa fora [^a-z]. E assim [^a-z] é a negação de [a-z].

[A-Z] é uma faixa fora [^a-z]. E assim [^a-z] é a negação de [a-z].

Outras negativas existem.

Combinando espaços de branco

"Ou \ t ou \ r ou \ n ou \ f é um personagem de espaço em branco. No código a seguir, o regex, "\ n" corresponde a '\ n' no alvo:

if (regex_search ("da linha um.\ r \ nof line dois.", regex (" \ n ")))))
cout << "matched" << endl;

Combinando qualquer personagem de espaço em branco

O padrão ou classe para corresponder a qualquer personagem do espaço em branco é [\ t \ r \ n \ f]. No código a seguir, "é comparado:

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

Corresponder a qualquer personagem não-branco

O padrão ou classe para corresponder a qualquer caractere de espaço não branco é, [^ \ t \ r \ n \ f]. O código a seguir produz uma correspondência porque não há espaço em branco no alvo:

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 inclusive, exceto \ n, no alvo. Uma partida é produzida no código a seguir:

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

Nenhuma correspondência resulta no código a seguir, porque o alvo é "\ n".

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

Nota: Dentro de uma classe de personagens com colchetes, o período não tem significado especial.

Repetições correspondentes

Um personagem ou um grupo de caracteres pode ocorrer mais de uma vez dentro da string de destino. Um padrão pode corresponder a esta repetição. Os Metacharacters, ?, *, +e são usados ​​para corresponder à repetição no alvo. Se x é um caráter de interesse na sequência de destino, os Metacharacters têm os seguintes significados:

x*: significa corresponder 'x' 0 ou mais vezes, eu.e., qualquer número de vezes
x+: significa corresponder 'x' 1 ou mais vezes, eu.e., pelo menos uma vez
x? : significa corresponder 'x' 0 ou 1 tempo
x n,: significa corresponder '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 metacaracters são chamados de quantificadores.

Ilustrações

*

O * corresponde ao caráter ou grupo anterior, zero ou mais vezes. "O*" corresponde a 'o' em "Dog" da corda de destino. Ele também corresponde a "oo" em "Book" e "Looking". O regex, "O*" combina "boooo" em "The Animal booooed.”. Nota: “O*” corresponde a “Dig”, onde 'O' ocorre zero (ou mais) tempo.

+

O + corresponde ao caráter ou grupo anterior, 1 ou mais vezes. Contraste com zero ou mais vezes para *. Então o regex, "e+" corresponde a 'e' em "Eat", 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 caráter ou grupo anterior, 0 ou 1 tempo (e não mais). Então, “e?"Combina" Dig "porque 'e' ocorre em" Dig ", Zero Time. “E?"Combina" Set "porque 'e' ocorre em" Set ", uma vez. Nota: “E?"Ainda corresponde a" ovelhas "; Embora haja dois 'E's em "Ovelha". Há uma nuance aqui - veja mais tarde.

n,

Isso corresponde a pelo menos n repetições consecutivas de um caráter ou grupo anterior anterior. Então, o regex, "e 2," corresponde aos dois 'E's no alvo, "ovelha", e os três' e estão no alvo "sheeep". "E 2," não corresponde a "conjunto", porque "Set" tem apenas um 'e'.

n

Isso corresponde exatamente às repetições consecutivas de um caráter ou grupo anterior anterior. Então o regex, "e 2" corresponde aos dois 'E's no alvo, "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

Isso corresponde a várias repetições consecutivas de um personagem ou grupo anterior anterior, de N a M, inclusive. Então, "E 1,3" não corresponde nada em "Dig", que não tem 'e'. Combina o 'e' em "set", os dois 'e estão em "ovelhas", os três' e estão em "sheeep" e três 'e estão em "sheeeep". Há uma nuance na última partida - veja mais tarde.

Alternância correspondente

Considere a seguinte sequência de destino no computador.

“A fazenda tem porcos de tamanhos diferentes.”

O programador pode querer saber se esse 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;
outro
cout << "not matched" << endl;

O código produz uma partida. Observe o uso do caractere de alternância, |. Pode haver duas, três, quatro e mais opções. C ++ primeiro tentará corresponder à primeira alternativa, "Goat", em cada posição de caractere na sequência de destino. Se não for bem -sucedido com "cabra", tenta a próxima alternativa, "Rabbit". Se não for bem -sucedido com "coelho", tenta a próxima alternativa, "porco". Se "porco" falhar, então C ++ passará para a próxima posição no alvo e começará com a primeira alternativa novamente.

No código acima, "porco" é comparado.

Combinando ou fim

Começo


Se ^ estiver no início do regex, o texto inicial da string de destino pode ser correspondido pela regex. No código a seguir, o início do alvo é "ABC", que é comparado:

if (regex_search ("abc e def", regex ("^abc"))))
cout << "matched" << endl;

Nenhuma correspondência ocorre no seguinte código:

if (regex_search ("sim, abc e def", regex ("^abc"))))
cout << "matched" << endl;
outro
cout << "not matched" << endl;

Aqui, "ABC" não está no início do alvo.

Nota: O caractere circunflex, '^', é um metacaracter no início do regex, correspondendo ao início da string de destino. Ainda é um metacaracter no início da classe de personagens, onde nega a classe.

Fim

Se $ estiver no final do regex, o texto final da string de destino pode ser correspondido pelo regex. No código a seguir, o final do alvo é "XYZ", que é comparado:

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;
outro
cout << "not matched" << endl;

Aqui, "xyz" não está no final do alvo.

Agrupamento

Parênteses podem ser usados ​​para agrupar caracteres em um padrão. Considere o seguinte regex:

"Um concerto (pianista)"

O grupo aqui é "pianista" cercado pelos Metacharacters (e). Na verdade, é um subgrupo, enquanto "um concerto (pianista)" é o grupo inteiro. Considere o seguinte:

"O (pianista é bom)"

Aqui, o subgrupo ou sub-cordão é: “Pianista é bom”.

Substrings com peças comuns

Um contador é uma pessoa que cuida de livros. Imagine uma biblioteca com um contador e uma estante de livros. Suponha que uma das seguintes cordas de destino esteja no computador:

"A biblioteca tem uma estante que é admirada.";
"Aqui está o contador.";
"O contador trabalha com a estante de livros.";

Suponha que o interesse do programador não seja saber qual dessas frases está no computador. Ainda assim, seu interesse é saber se "estante de livros" ou "contador" está presente em qualquer string de destino que esteja no computador. Nesse caso, seu regex pode ser:

"Estante de livros | contador."

Usando alternância.

Observe que "livro", que é comum a ambas as palavras, foi digitado duas vezes, nas duas palavras no padrão. Para evitar digitar o "livro" duas vezes, o regex seria melhor escrito como:

"Livro (prateleira | guardião)"

Aqui, o grupo, “prateleira | guardião”, a alternância metacaracter ainda foi usada, mas não para duas palavras longas. Foi usado para as duas partes finais das duas palavras longas. C ++ trata um grupo como uma entidade. Então, o C ++ procurará "prateleira" ou "goleiro" que vem imediatamente após o "livro". A saída do código a seguir é "correspondente":

char str [] = "A biblioteca tem uma estante de livros que é admirada.";
if (regex_search (str, regex ("livro (prateleira | guardião)")))))
cout << "matched" << endl;

"Bookshelf" e não "contador" foram combinados.

A ICASE e multiline regex_constants

ICASE

A correspondência é sensível ao maiúsculas por padrão. No entanto, pode ser tornado insensível ao caso. Para conseguir 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 é "correspondente". Então, "feedback" com a maçaneta 'f' foi combinada com "Feed" com minúsculas 'f'. "Regex :: ICase" foi feito o segundo argumento do construtor regex (). Sem isso, a declaração não produziria uma partida.

Multilina

Considere o seguinte código:

char str [] = "Linha 1 \ nline 2 \ nline 3";
if (regex_search (str, regex ("^.*$ "))))
cout << "matched" << endl;
outro
cout << "not matched" << endl;

A saída "não corresponde". O regex, “^.*$ ”, Corresponde à sequência de destino desde o seu início até o fim. ““.*”Significa qualquer personagem, exceto \ n, zero ou mais vezes. Então, por causa dos caracteres da nova linha (\ n) no alvo, não havia correspondência.

O alvo é uma corda multilina. A fim de '.'Para combinar com o personagem Newline, a constante “regex :: multiline” deve ser feita, o segundo argumento da construção regex (). O código a seguir ilustra o seguinte:

char str [] = "Linha 1 \ nline 2 \ nline 3";
if (regex_search (str, regex ("^.*$ ", regex :: multiline))))
cout << "matched" << endl;
outro
cout << "not matched" << endl;

Combinando toda a string alvo

Para corresponder a toda a string de destino, que não possui o caractere novo (\ n), a função regex_match () pode ser usada. Esta função é diferente de regex_search (). O código a seguir ilustra o seguinte:

char str [] = "Primeiro segundo terço";
if (regex_match (str, regex (".*segundo.*")))
cout << "matched" << endl;

Há uma partida aqui. No entanto, observe que o regex corresponde a toda a sequência de destino e a sequência de destino não possui nenhum '\ n'.

O objeto Match_Results

A função regex_search () pode levar um argumento entre o alvo e o objeto regex. Este argumento é o objeto Match_results. Toda a string (parte) correspondente e as sub-strings correspondentes podem ser conhecidas com ela. Este objeto é uma matriz especial com métodos. O tipo de objeto Match_Results é cmatch (para literais de string).

Obtendo correspondências

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 sequência de alvo tem a palavra "mulher". A saída é "mulher", que corresponde ao regex, "w.m.n ”. No índice zero, a matriz especial é a única partida, que é "mulher".

Com as opções de classe, apenas a primeira sub-cordão encontrada no alvo é enviada para a matriz especial. O código a seguir ilustra o seguinte:

cmatch m;
if (regex_search ("o rato, o gato, o morcego!", M, regex (" [bcr] em "))))
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 sub-cordão encontrada no alvo é enviada para a matriz especial. O código a seguir ilustra o seguinte:

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 comparado, entra na célula zero da matriz especial. A próxima sub-cordão encontrada entra na célula 1; A sub-string a seguir, entra na célula 2; e assim por diante. O código a seguir ilustra o seguinte:

if (regex_search ("Melhor livreiro hoje!", M, regex (" Livro ((sel) (ler)) ")))))
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;

A saída é:

livreiro
vendedor
Sel
ler

Observe que o grupo (vendedor) vem antes do grupo (SEL).

Posição da partida

A posição de correspondência para cada sub-string na matriz CMATCH pode ser conhecida. A contagem começa a partir do primeiro caractere da sequência de alvo, na posição zero. O código a seguir ilustra o seguinte:

cmatch m;
if (regex_search ("Melhor livreiro hoje!", M, regex (" Livro ((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 de posição, com o índice celular, como argumento. A saída é:

livreiro-> 5
Vendedor-> 9
Sel-> 9
Ler-> 12

Pesquise e substitua

Uma nova palavra ou frase pode substituir a correspondência. A função regex_replace () é usada para isso. No entanto, desta vez, a sequência em que a substituição ocorre é o objeto String, não a string literal. Portanto, a biblioteca de string 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 ("man"), "mulher");
cout << newStr << endl;
retornar 0;

A função regex_replace (), como codificada aqui, substitui todas as correspondências. O primeiro argumento da função é o alvo, o segundo é o objeto Regex, e o terceiro é a sequência de substituição. A função retorna uma nova string, que é o alvo, mas com a substituição. A saída é:

“Aqui vem minha mulher. Lá vai sua mulher.”

Conclusão

A expressão regular usa padrões para combinar com substâncias na sequência de sequência de destino. Os padrões têm metacaracters. Funções comumente usadas para expressões regulares C ++, são: regex_search (), regex_match () e regex_replace (). Um regex é um padrão em citações 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.