Alguns de nossos parceiros estão com ofertas especiais em cursos de programação e de Inglês. Confira os cursos, seus cupons de desconto e inicie 2020 atualizado.

Regex – Como definir 2 limites e pegar todo conteúdo dentro?

Regex – Como definir 2 limites e pegar todo conteúdo dentro?

24 de agosto de 2019 0 Por Ramos de Souza Janones
Powered by Rock Convert

Dica sobre programação usando Regex – Como definir dois limites e pegar todo conteúdo dentro. Um exemplo prático passo a passo completo.

Considerando que o delimitador terminal só pode aparecer uma única vez, e que ele é de apenas um caractere no seu exemplo é o %), fiz um pequeno ajuste na resposta do nullptr para tal fim:

ENERGIA ELETRICA CONSUMO[^%]*%

Agora, em termos gerais:

Para qualquer sequência iniciadora INIT, podendo ela ser repetida na sequência, e um terminador @de um caracter que não pode estar contido exceto no final da sequência:

INIT[^@]*@

Para um iniciador qualquer de um caracter £ que não pode ser repetido dentro e um terminador de um caracter que também não pode ser repetido:

£[^£@]*@

Se for plausível aceitar um caracter de escape (fingindo ser o #), em que o escape pode se escapar também, e que o iniciador £ ou o terminador @ podem ser escapados no meio da sequência (não podendo aparecer livres):

£([^#£@]|#.)*@

Aqui, vale uma explicação:

Leia também:  
  • começa com £, como esperado de um iniciador
  • termina com um @, como esperado de um terminador
  • pode conter um grupo com diversas repetições de g1 ou g2
  • g1 é qualquer caracter que não seja escape, iniciador ou terminador
  • g2 é o escape seguido de qualquer coisa, incluindo (mas não limitado a): iniciador, escape e terminador

Como consequência da montagem de g1, um escape só poderá aparecer em elemento de g2. E g2começa garantidamente com um escape e tem um outro caracter; logo, não há escapes faltando, eles estão sempre seguidos de algo.

SQL e Regex – Entenda quando e como usar em instruções SQL

Se por acaso a sequência que não pode se repetir no meio for de mais de 1 caracter, a coisa fica um pouco mais complicada e feia de se escrever.

Note que estou usando aqui apenas regex “pura”, possível de ser representada por um autômato de estados finito; logo, retrovisores estão fora do meu escopo de escrita abaixo

Tome, por exemplo, a sequência @€ como terminadora, e que eu preciso que ela não se repita. Assumindo que o iniciador £ pode se repetir, e também na ausência de escapes.

Um simples @ não significa que a sequência foi preenchida. Para tal, é necessário que o próximo caracter não seja . E também pode ocorrer o caso de que o @ seja a parte logo anterior ao terminador @€. Então eu preciso pegar, no miolo da regex:

  • um @ sucedido por qualquer coisa que não seja 
  • o próprio  desde que garantido que não haja algum casamento com algo que termine em @ no meio da repetição
  • possivelmente uma fração do terminador

Posso separar o miolo na parte de passível repetição e na parte de incompletude. Assim, a parte de incompletude, para um terminador de 2 caracteres apenas, é (@+)? (já já explico a cruz de Kleene). E a parte passível de repetição?

([^@]|@+[^€])*

Assim, eu posso ter uma sequência arbitrária dentro dessa repetição que, garantidamente, não vai terminar com @. A repetição é composta de 2 grupos: g1 que é qualquer coisa menos o primeiro caracter do terminador, e g2, que é o caracter iniciador seguido de necessariamente algo que quebre a sequência do terminador.

Então, para permitir também a parte inicial do terminador, permito que seu primeiro caracter se repita infinitamente, de modo opcional, após essa sequência, ficando assim toda a regex:

Curso completo de Games, inclusive Realidade Aumentada.Powered by Rock Convert
£([^@]|@+[^€])*(@+)?@€

E se o terminador fosse de 3 caracteres? Como o @€¥?

Bem, a ideia é semelhante, mas vai precisar negar no primeiro caractere, no segundo caractere e no terceiro caractere a sequência. Como fazemos isso?

  • a negação do primeiro caracter é direta: [^@]
  • a negação do segundo caracter em diante deve assumir a presença do primeiro caracter, com possibilidade de repetição, então vou colocá-las todas em um grupo precedido de @*
  • a negação do segundo caracter (já considerando que foi tratada externamente a repetição do primeiro caracter), começa assumindo que seu casamento positivo para o primeiro caracter e negando o segundo caracter: @[^€]
  • a negação do terceiro caracter (também assumindo que já foi tratada a repetição do primeiro caracter) precisa assumir que deram certo os dois primeiros caracteres: @€[^¥]

Então, fica assim a parte passível de repetição:

([^@]|@*(@[^€]|@€[^¥]))*

Para a parte de sequência incompleta, só tirar as listas negadas e a estrela de Kleene final, substituindo-a pela possibilidade de presença. Vou denotar como '' a string de comprimento 0 apenas por uma questão de visualização, em seguida eliminando-a:

(''|@*(@''|@€''))?

Como não faz sentido algo concatenado da string vazia na regex desejada:

(''|@*(@|@€))?

Como não faz sentido a opção entre nada ou outra coisa, sempre recaindo sobre a outra coisa:

(@*(@|@€))?

Poderia seguir aqui apenas com isso, mas, se você prestar atenção, isso pode ser substituído por algo mais expressivo:

(@*(@(€)?)?)?

Onde cada parêntese após a repetição do primeiro caractere da sequência terminadora indica que é opcional aquela subsequência. Note, também, que só faria sentido dar casamento nesse grupo se e somente se tiver pelo menos uma parte da sequência, e que necessariamente deve ser o primeiro caractere. Portanto, isso poderia ser reescrito assim:

(@+(€)?)?

Tirando parênteses redundantes:

(@+€?)?

Note, porém, que esse mesmo algoritmo poderia ser usado para uma string arbitrária abcdefX:

(a+(b(c(d(ef?)?)?)?)?)? 

Essa expressão casa com qualquer subsequência do início de abcdefX

E como ficaria toda a expressão?

£([^@]|@*(@[^€]|@€[^¥]))*(@+€?)?@€¥

Dá para expandir essa lógica para mais caracteres, mas devo assumir que é bem trabalhoso e o tamanho aumenta exponencialmente. Também não levei em consequência a possibilidade de haver caracteres repetidos na sequência terminadora, isso pode eventualmente gerar um caso complexo que não foi devidamente tratado.

» Programação

React Native Do Zero Ao Profissional: crie apps para Android e IOSPowered by Rock Convert
Siga os bons!

Ramos de Souza Janones

Janones, é um empreendedor brasileiro apaixonado por empreendedorismo e tecnologia. Ao longo dos anos trabalhando com o desenvolvimento de softwares desktop desde a linguagem Clipper, passando pelo Delphi e atualmente com Java.

Optou pela formação de Publicidade e Marketing por sua segunda empresa de tecnologia ter participado do "boom" da internet nos anos 90 e na procura de melhorar seus conhecimentos em negócios.

Em razão da principal formação e profundos conhecimentos em programação e banco de dados, é capaz de realizar o desenvolvimento de aplicativos web, desktop e mobile com maior criatividade e inovação que profissionais de desenvolvimento com uma formação única e mais especifica, dedicada somente ao desenvolvimento de softwares.

Com toda sua experiência com empresas de software, sua formação e paixão por negócios escreveu o livro "Marketing para Empresas e Profissionais de Software", publicado pela editora carioca Ciência Moderna em 2012. Além de outros livros sobre programação.

Últimos posts por Ramos de Souza Janones (exibir todos)




Frontend Do Zero Ao Profissional