Noções básicas de expressão regular em C ++

Regular Expression Basics C



Considere a seguinte frase entre aspas:

'Aqui está o meu homem.'

Essa 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 os fundamentos da expressão regular em C ++.



Conteúdo do Artigo

Fundamentos da expressão regular

Regex

Uma corda como Here is my man. acima está a sequência alvo ou string alvo ou simplesmente alvo. man, que foi procurado, é 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 o homem está localizado acima, ele pode ser substituído pela mulher.

Correspondência Simples

O programa a seguir mostra como a palavra homem é combinada.



#incluir

#incluir

usando namespace std;

inta Principal()
{

regex reg('cara');
E se (regex_search('Aqui está o meu homem.',reg))
custo<< 'coincide' <<endl;
outro
custo<< 'não correspondido' <<endl;

Retorna 0;
}

A função regex_search () retorna verdadeiro se houver uma correspondência e retorna falso se nenhuma correspondência ocorrer. 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', visto que '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 'não correspondida'.

A saída do seguinte código não é correspondida:

regex reg('cara');
E se (regex_search('Aqui está minha fabricação.',reg))
custo<< 'coincide' <<endl;
outro
custo<< 'não correspondido' <<endl;

Sem correspondência 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. As 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 está na sala.'

'O morcego está na sala.'

'O rato está na sala.'

A regex, [cbr] em corresponderia a cat no primeiro destino. Seria igual ao morcego no segundo alvo. Corresponderia ao rato no terceiro alvo. Isso ocorre porque gato, morcego ou rato começa com 'c' ou 'b' ou 'r'. O seguinte segmento de código ilustra isso:

regex reg('[cbr] em');
E se (regex_search('O gato está na sala.',reg))
custo<< 'coincide' <<endl;
E se (regex_search('O morcego está na sala.',reg))
custo<< 'coincide' <<endl;
E se (regex_search('O rato está na sala.',reg))
custo<< 'coincide' <<endl;

O resultado é:

coincide

coincide

coincide

Gama de personagens

A classe, [cbr] no padrão [cbr], corresponderia a vários caracteres possíveis no destino. Ele corresponderia a 'c' ou 'b' ou 'r' no destino. Se o alvo não tiver nenhum 'c' ou 'b' ou 'r', seguido por at, 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]. A faixa 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:

E se (regex_search('ID6id',regex('[0-9]')))

custo<< 'coincide' <<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:

E se (regex_search('ID6id',regex('[0123456789]')))

custo<< 'coincide' <<endl;

O código a seguir produz uma correspondência:

Caracteresp[] = 'ID6iE';

E se (regex_search(p,regex('[a-z]')))

custo<< 'coincide' <<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 de 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:

E se (regex_search('ID2id é um ID ',regex('ID [0-9] id')))

custo<< 'coincide' <<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.

Nota: 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:

E se (regex_search('0123456789101112',regex('[^ 0-9]')))

custo<< 'coincide' <<endl;

outro

custo<< 'não correspondido' <<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:

E se (regex_search('ABCDEFGHIJ',regex('[^ 0-9]')))

custo<< 'coincide' <<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:

E se (regex_search(- Da linha um. r nDa linha dois. ',regex(' n')))

custo<< 'coincide' <<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:

E se (regex_search('um dois',regex('[ t r n f] ')))

custo<< 'coincide' <<endl;

Combinando qualquer caractere sem espaço em branco

O padrão ou classe para corresponder a qualquer caractere de espaço nã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:

E se (regex_search('1234abcd',regex('[^ t r n f] ')))

custo<< 'coincide' <<endl;

O ponto (.) No padrão

O ponto (.) No padrão corresponde a qualquer caractere incluindo ele mesmo, exceto n, no destino. Uma correspondência é produzida no seguinte código:

E se (regex_search('1234abcd',regex('.')))

custo<< 'coincide' <<endl;

Nenhum resultado correspondente no código a seguir porque o destino é n.

E se (regex_search(' n',regex('.')))

custo<< 'coincide' <<endl;

outro

custo<< 'não correspondido' <<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 na string de destino. Um padrão pode corresponder a essa repetição. Os metacaracteres,?, *, + E {} são usados ​​para corresponder à repetição no destino. Se x é um caractere de interesse na string de destino, os metacaracteres têm os seguintes significados:

x*:significa partida'x' 0ou mais vezes,eu.E.,qualquer número de vezes

x+:significa partida'x' 1ou mais vezes,eu.E.,pelo menos uma vez

x? :significa partida'x' 0ou1 Tempo

x{n,}:significa partida'x'pelo menos n ou mais vezes.Observaçãoa vírgula.

x{n} :partida'x'exatamente n vezes

x{n,m}:partida'x'pelo menos n vezes,mas não mais do que m vezes.

Esses metacaracteres são chamados quantificadores.

Ilustrações

*

O * corresponde ao caractere anterior ou ao grupo anterior, nenhuma ou mais vezes. o * corresponde a 'o' em dog da string alvo. Também corresponde a oo em book e looking. O regex, o * corresponde a boooo em The animal booooed .. Nota: o * corresponde a dig, onde ‘o’ ocorre zero (ou mais) vez.

+

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 ovelhas, 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 ao 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 ao conjunto porque 'e' ocorre no conjunto, uma vez. Nota: e? ainda combina com ovelhas; embora haja dois 'e's em ovelhas. Há uma nuance aqui - veja mais tarde.

{n,}

Isso corresponde a pelo menos n repetições consecutivas de um caractere anterior ou grupo anterior. Assim, o regex, e {2,} corresponde aos dois 'e's no alvo, ovelha, e os três' e's no sheeep alvo. e {2,} não corresponde ao conjunto, porque o conjunto possui 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 ao conjunto porque o conjunto 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. Então, e {1,3} não corresponde a nada em dig, que não tem 'e'. Corresponde a um 'e' no conjunto, os dois 'e's em ovelhas, 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 possui porcos de diversos tamanhos.

O programador pode querer saber se este alvo tem cabra, coelho ou porco. O código seria o seguinte:

Caracteresp[] = 'A fazenda tem porcos de tamanhos diferentes.';

E se (regex_search(p,regex('cabra | coelho | porco')))

custo<< 'coincide' <<endl;

outro

custo<< 'não correspondido' <<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 a cabra, ele tenta a próxima alternativa, coelho. Se não tiver sucesso com o 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:

E se (regex_search('abc e def',regex('^ abc')))

custo<< 'coincide' <<endl;

Nenhuma correspondência ocorre no seguinte código:

E se (regex_search('Sim, abc e def',regex('^ abc')))

custo<< 'coincide' <<endl;

outro

custo<< 'não correspondido' <<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 caractere, onde nega a classe.

Fim

Se $ estiver no final da regex, 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:

E se (regex_search('uvw e xyz',regex('xyz $')))

custo<< 'coincide' <<endl;

Nenhuma correspondência ocorre no seguinte código:

E se (regex_search('uvw e xyz final',regex('xyz $')))

custo<< 'coincide' <<endl;

outro

custo<< 'não correspondido' <<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

O contador é uma pessoa que cuida dos 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 a estante ou o contador está presente em qualquer string de destino no computador. Nesse caso, sua regex pode ser:

'estante | contador.'

Usando alternância.

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

'livro (estante | guardião)'

Aqui, o grupo, shelf | keeper O metacaractere de alternância ainda é 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. Portanto, C ++ irá procurar por estantes ou guardiões que vêm imediatamente após o livro. A saída do seguinte código é correspondida:

Caracteresp[] = 'A biblioteca tem uma estante que é admirada.';

E se (regex_search(p,regex('livro (estante | guardião)')))

custo<< 'coincide' <<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 feito sem distinção entre maiúsculas e minúsculas. Para fazer isso, use a constante regex :: icase, como no código a seguir:

E se (regex_search('Comentários',regex('alimentação',regex::icase)))

custo<< 'coincide' <<endl;

A saída é correspondida. Portanto, o feedback com 'F' maiúsculo foi correspondido pelo 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:

Caracteresp[] = 'linha 1 nlinha 2 nlinha 3 ';

E se (regex_search(p,regex('^. * $')))

custo<< 'coincide' <<endl;

outro

custo<< 'não correspondido' <<endl;

A saída não é correspondida. A regex, ^. * $, Corresponde à string de destino do início ao fim. . * significa qualquer caractere, exceto n, zero ou mais vezes. Portanto, por causa dos caracteres de nova linha ( n) no destino, não houve correspondência.

O alvo é uma string multilinha. Para que ‘.’ Corresponda 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:

Caracteresp[] = 'linha 1 nlinha 2 nlinha 3 ';

E se (regex_search(p,regex('^. * $',regex::multilinha)))

custo<< 'coincide' <<endl;

outro

custo<< 'não correspondido' <<endl;

Correspondência de toda a string de destino

Para corresponder a toda a string de destino, que não possui 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:

Caracteresp[] = 'primeiro segundo terceiro';

E se (regex_match(p,regex('.*segundo.*')))

custo<< 'coincide' <<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:

Caracteresp[] = - A mulher que você estava procurando!;

cmatch m;

E se (regex_search(p,m,regex('w.m.n')))

custo<<m[0] <<endl;

A string de destino contém a palavra mulher. A saída é woman ’, 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 subcadeia encontrada no destino é enviada para a matriz especial. O código a seguir ilustra isso:

cmatch m;

E se (regex_search('O rato, o gato, o morcego!',m,regex('[bcr] em')))

custo<<m[0] <<endl;

custo<<m[1] <<endl;

custo<<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:

E se (regex_search('O coelho, a cabra, o porco!',m,regex('cabra | coelho | porco')))

custo<<m[0] <<endl;

custo<<m[1] <<endl;

custo<<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 do array 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:

E se (regex_search('Melhor livreiro hoje!',m,regex('livro ((sel) (ler))')))

custo<<m[0] <<endl;

custo<<m[1] <<endl;

custo<<m[2] <<endl;

custo<<m[3] <<endl;

O resultado é:

livreiro

vendedor

célula

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;

E se (regex_search('Melhor livreiro hoje!',m,regex('livro ((sel) (ler))')))

custo<<m[0] << '->' <<m.posição(0) <<endl;

custo<<m[1] << '->' <<m.posição(1) <<endl;

custo<<m[2] << '->' <<m.posição(2) <<endl;

custo<<m[3] << '->' <<m.posição(3) <<endl;

Observe o uso da propriedade position, com o índice da célula, como argumento. O resultado é:

livreiro->5

vendedor->9

célula->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;

inta Principal()
{
string str= 'Aqui, vem meu homem. Lá vai seu homem. ';
string newStr=regex_replace(p,regex('cara'), 'mulher');
custo<<newStr<<endl;

Retorna 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 tem a substituição. O resultado é:

Aí vem minha mulher. Lá vai sua mulher.

Conclusão

A expressão regular usa padrões para corresponder 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 consideram 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.