2017627 Regex — Como não se apaixonar?
– Bar8
Erick Carvalho Follow
Agilista, Desenvolvedor e quando não está discutindo TDD está sendo repreendido por algum comentá…
Jun 14 · 10 min read
Regex—Como não se apaixonar?
Expressões regulares—Como tornar as suas pesquisas
muito mais simples!
E aweeeeeeee meu povo bonito tudo bem com vocês?
Hoje falaremos de expressões criadas em linguagem formal que
acabaram por receber a denominação “regex” (a pronúncia fica algo
como “réGueks”, então não vai passar vergonha na hora de contar
para o amiguinho). O poder do regex é absurdo, lhe conferindo a
capacidade de Decidibilidade, Computabilidade e Complexidade
Computacional, além de uma vida muito mais tranquila com as
Strings.
Não vou mentir, eu sou apaixonado por regex, ou melhor, eu AMO
regex. Amo ver a cara de um desenvolvedor que não teve contato
algum com regex me observar enquanto converto uma lógica
complexa de manipulação de string em algo simples e banal.
Justamente por isso, hoje vamos falar a respeito deste assunto.
Falaremos o suficiente para que você não se assuste quando achar
alguma expressão como a seguinte pela frente (e nem pense que é
algo impossível de se entender): /[09]{3}\.?[09]{3}\.?[09]
{3}?([09]{2})?/
Expressões Regulares
Não vou me aprofundar demais no assunto, já que o meu foco hoje é
ser mais prático e menos teórico. Lá embaixo, nas indicações, vou
deixar alguns links para ajudar a aprofundar o seu conhecimento.
[Link] 1/17
2017627 Regex — Como não se apaixonar? – Bar8
Regular Expressions (ou simplesmente Regex) são padrões
utilizados para identificar determinadas ocorrências em uma cadeias
de caracteres.
Se você é graduado em algum curso relacionado a computação, muito
provavelmente estudou sobre autômato. As expressões regulares
vieram primeiramente na matemática e na teoria dos autômatos.
Expressões regulares possuem traços de expressões matemáticas
chamadas regularidade. Sentindo-se perdido em questões de
matemática? Talvez seja hora de conhecer o Mathematics Stack
Exchange, que nada mais é que o Stack Overflow para quem curte
matemática.
Em computação, por sua vez, expressões regulares podem ser
implementadas em software usando um autômato finito
determinístico (AFD). Um AFD é uma máquina de estado finito que
não usa backtracking.
Embora o nome expressão regular tenha permanecido, as coisas
mudaram e hoje as expressões regulares não são mais como as do
sentido matemático. As expressões que utilizamos no desenvolvimento
de software hoje são implementadas com um autômato finito não
determinístico (AFND).
No final das contas, o que importa é que expressões regulares fazem
parte do cotidiano de desenvolvedores e até mesmo do pessoal de
infra. Através delas podemos validar a entrada de usuários ou
encontrar alguma informação em diretórios, logs, documentação ou
saída de comando.
E, para mim, a parte mais sensacional de tudo:
Regex são escritas independentes de uma linguagem de programação.
Conforme citado acima, regex é implementado em linguagem formal,
o que o torna independente de qualquer linguagem e faz com que o
seu aprendizado seja ainda mais proveitoso.
Expressões Regulares na prática
Nesta primeira parte do post não vou apresentar exemplos utilizando
ABAP. Quero mostrar quão poderoso pode ser o regex e também uma
opção para que você possa prática-lo a qualquer momento no seu
cotidiano. Costumo utilizar o editor de texto sublime para aplicar as
[Link] 2/17
2017627 Regex — Como não se apaixonar? – Bar8
expressões regulares, mas também utilizo bastante o site Regex101.
Será nele que irei montar e mostrar toda a magia dessa belezinha.
Primeiramente, o que você deve saber é que regexs são aplicados
entre recursos conhecidos como delimitadores. Delimitadores são
representados por: // . Assim, todos os padrões que estiverem
dentro dos // servirão de base para correspondentes combinações.
Por exemplo:
Repare na expressão regular /Bar8/, que remete a string informada
logo abaixo. Observando o quadro à direita é possível ver que tivemos
um match, e aí está o seu primeiro regex.
Apesar de muito legal, um regex dessa forma não serve para muita
coisa, ou seja, algo desse tipo não é muito prático ou usual. Que tal
então um regex que encontre uma cadeia de letras? Uma cadeia de
números? Números, letras e símbolos? Vejamos como isso é possível,
passando por alguns recursos que eu julgo ser o básico na construção
de um regex.
Colchetes [x]
Os colchetes são capazes de dar match em algo que você não conhece
muito bem sobre uma string que você esteja procurando. Por exemplo,
se você estiver procurando por um nome em uma string, mas não tem
certeza de qual letra exatamente poderia ser, ao invés desta letra você
pode utilizar colchetes, aumentando a gama da pesquisa. Exemplo:
/[B]ar8/
Este caso serve mais a título de ilustração. Um regex desse não faz muito sentido, ainda!
[Link] 3/17
2017627 Regex — Como não se apaixonar? – Bar8
/[BLC]ar8/
Aqui SIM já podemos começar a ver a utilidade de colchetes. Neste exemplo, eu consigo dar match em
qualquer palavra começada em B, L ou C e que seja seguida de "ar8".
/[BLC]ar[854]/
Este exemplo mostra que você pode utilizar colchetes em qualquer posição da string
Range—Ou De-Até [X-Y], no bom e velho português
Ainda utilizando colchetes, faremos a adição de um hífen para que,
então, passemos a ter uma poderosa opção quando precisarmos
validar algum range numérico e/ou até de letras. Por exemplo:
/[AZ]ar8/
[Link] 4/17
2017627 Regex — Como não se apaixonar? – Bar8
Neste exemplo iremos ter um match de todas as palavras começadas de A até Z e änalizadas em “ar8”. No
entanto, perceba que existe distinção entre letras maiúsculas e minúsculas e, por este motivo, não tivemos um
match na última palavra. Como eu disse, estamos procurando palavras que comecem com A até Z, desde que
sejam maiúsculas.
/[AZaz]ar8/
Temos aqui um regex capaz de encontrar intervalos de A-Z e de a-z. Observação: caracteres especiais como "Ç"
ou palavras acentuadas não entram neste range — existe uma forma especial de Regex para estes casos.
/[AZ]ar[09]/
Com números o range funciona da mesma forma, e diria até que de forma mais sugestiva.
SQN!—Tudo menos… [^x]
Apenas reforçando a grandiosidade e poder dos colchetes, apresento-
lhes o símbolo capaz de fazer com que sua expressão ignore
caracteres:
/[^CL]ar8/
[Link] 5/17
2017627 Regex — Como não se apaixonar? – Bar8
Neste exemplo nossa expressão irá ignorar tudo que comece com C ou L e termine com "ar8". Poderíamos
aplicar também a opção range em conjunto.
Qualquer caracter—"." (ponto)
Este é um exemplo, dentre vários outros, do que chamamos de
metacaracter. Neste caso o utilizamos onde você não deseja especificar
se o símbolo em questão é uma letra ou número ou qualquer outra
coisa. Nesta situação, você poderá fazer uso do . (ponto).
/.ar8/
Perceba que não importa qual caracter ou símbolo começar a palavra, desde que seja änalizada com "ar8",
teremos um match.
Quantiäers—* + ?
O * ou ? ou + são outros meta-caracteres que, através de sua
utilização, conseguimos definir a quantidade de algo (por isso são
também chamados de quantifiers). As diferenças entre estes
quantifiers são:
? = 01 = Corresponde apenas a zero ou a uma ocorrência.
+ = 1n = Corresponde a ocorrências infinitas, mas nunca
a zero.
* = 0n = Corresponde zero, uma ou ocorrências
infinitas.
A aplicação de quantifiers é extremamente poderosa e útil. Isto
porque, se tivéssemos, por exemplo, apenas a utilização de colchetes
para tornar a nossa expressão regular mais dinâmica e flexível,
seguindo os exemplos anteriores, teríamos que construir algo assim:
/[AZ][az][az][09]/
[Link] 6/17
2017627 Regex — Como não se apaixonar? – Bar8
Isto não é nem um pouco dinâmico. Imagine só se ao invés de procurar uma palavra a sua busca fosse por uma
sentença inteira? Você teria muito mais trabalho.
Então, já que sabemos que iremos precisar de uma opção para
repetição, vamos utilizar quantifiers para tornar o nosso regex mais
simples. Exemplo:
/[AZ][az]*[09]/
Neste exemplo temos uma expressão que diz: Começando com qualquer letra maíuscula de A até Z e que
termine com qualquer número de zero até nove, não importa quantos caracteres inserimos no meio disso,
teremos um match.
Unindo dois metacaracteres, o ponto busca por qualquer coisa, e o asterisco pontencializa a busca de qualquer
coisa ao inänito.
Quantiäers—Deixando a repetição mais especíäca {x}
Nas opções anteriores, qualquer um dos quantifiers não nos dá muita
opção para sermos mais precisos durante a repetição. Entretanto,
graças à opção de { } (chaves), podemos resolver este problema.
Exemplo:
[Link] 7/17
2017627 Regex — Como não se apaixonar? – Bar8
/[09]{3}/
Toda vez que existir um grupo numérico na ordem de centena teremos um match. Este seria um exemplo muito
útil para casos de uma pequisa por CPF. Porém não teríamos encontrado os últimos dois dígitos.
/[09]{2,3}/
Acrescentando dentro das chaves uma virgula, ganhamos a capacidade de termos um "OU" que, nesse caso,
signiäca: Pesquise a ocorrência de grupos numéricos de zero a nove na ordem de dezena ou centena. Porém,
note que ainda temos problemas com os pontos e o hífen na composição do CPF.
/[09]{3}\.?[09]{3}\.?[09]{3}?[09]{2}/
Não precisa se desesperar ainda, o que äzemos agora para conseguirmos buscar expressões que correspondam
a um CPF é muito simples, veja abaixo:
Para este exemplo, vamos assumir que um CPF sempre será
composto por três grupos numéricos na ordem de centena
separados por pontos, sendo finalizado por um grupo
numérico na ordem de dezena separado por um hífen.
Teremos, então, um regex da seguinte maneira:
[09]{3} Expressão que irá dar match no primeiro grupo
numérico;
[Link] 8/17
2017627 Regex — Como não se apaixonar? – Bar8
\.? Expressão que irá dar match no ponto. Perceba a
utilização da barra invertida: lembrese de que o
símbolo . (ponto) na linguagem formal é um exemplo de
metacaracter daí utilizarmos a barra invertida sempre
que queremos inutilizar o super poder de um
metacaracter, tornandoo apenas um caracter normal. Além
de dar match no ponto, estamos utilizando um quantifier
que garante a correspondência de zero ou um caracter
especificado, que neste caso é o ponto;
[09]{3} Expressão que irá dar match no segundo grupo
numérico;
\.? Expressão que irá dar match no ponto.
[09]{3} Expressão que irá dar match no terceiro grupo
numérico;
? Expressão que irá dar match no hífen perceba que
não precisamos escapar o hífen com barra invertida neste
caso, pois o hífen fora de colchetes não é um
metacaracter. Além disso, estamos utilizando um
quantifier para garantir que seja encontrado zero ou um.
Já vi casos em que ao invés da utilização de hífen para
separação dos dígitos no CPF, era utilizado ponto
também, então para esta situação poderíamos utilizar a
seguinte expressão: [.] (ponto ou hífen). Perceba que
dentro de colchetes não precisamos escapar o ponto, isto
porque dentro de colchetes ele possui seu valor literal;
[09]{2} Enfim expressão que irá dar match no último
grupo de caracteres.
Grupos—(x)
Seguindo ainda o exemplo anterior do CPF, além de ter conseguido
um match com uma string correspondente à expressão, você precisa
destacar apenas os dígitos do CPF. Para isto iremos utilizar o recurso
de grupos. Veja o exemplo:
/[09]{3}\.?[09]{3}\.?[09]{3}?([09]{2})/
Colando apenas a expressão correspondente aos dois últimos dígitos entre parênteses somos capazes de
destacar um grupo de caracteres dentro de um match.
[Link] 9/17
2017627 Regex — Como não se apaixonar? – Bar8
Grupos podem ser ainda mais úteis quando aliados com o meta-
char ? . Assim, podemos também definir um conjunto de caracteres
como opcional. Ainda no exemplo do CPF, digamos que existam casos
em que os dígitos do CPF não são obrigatórios, o que faria com que a
nossa expressão não funcionasse. Porém, com o recurso de grupos,
temos o seguinte:
/[09]{3}\.?[09]{3}\.?[09]{3}?([09]{2})?/
Perceba que, na segunda string, mesmo não passando o dígito, o nosso regex continua funcionando!
Mais poder para o seu Regex com mais alguns meta-
char—/\w/ e /\d/
Ao invés de sermos tão específicos detalhando a busca por caracteres
utilizando /[az]/ , podemos simplesmente optar pelo uso da
expressão /\w/.
Perceba que eu preciso utilizar a barra invertida para escapar o símbolo
“w”, caso contrário o compilador entenderia que estávamos procurando
literalmente apenas pela letra “w”. Neste caso, porém, estamos falando de
mais um metacaracter. Exemplo:
[Link] 10/17
2017627 Regex — Como não se apaixonar? – Bar8
Entretanto se você quiser delimitar sua busca apenas a números nós
podemos subistruir /[09]/ simplesmente por /\d/ . Exemplo:
Perceba a explicação, a opção /\d/ combina apenas dígitos de 0 a 9.
Existem vários outros metacaracteres que podem ser utilizados. No
site do Regex101 existe um quadro de quick references que detalha
muito bem vários tipos de expressões regulares que seguem o mesmo
princípio do que vimos aqui.
[Link] 11/17
2017627 Regex — Como não se apaixonar? – Bar8
Mas como podemos aplicar isso em ABAP?
A aplicação de regex em ABAP é muito simples. Conheço basicamente
dois modos de utilizar regex. O primeiro é com a seguinte sintaxe:
[Link] 12/17
2017627 Regex — Como não se apaixonar? – Bar8
1 * Encontando correspondências do regex
2 FIND ALL OCCURRENCES OF
3 REGEX '/[0‐9]{3}\.?[0‐9]{3}\.?[0‐9]{3}‐?([0‐9]{2})?/' IN
4
5 * Encontrando e substituindo todas as ocorrências do regex
6 REPLACE ALL OCCURRENCES OF
7 REGEX '/[0‐9]{3}\.?[0‐9]{3}\.?[0‐9]{3}‐?([0‐9]{2})?/' IN lv_texto
8 WITH lv_novo_texto.
9
10 * Aplicação
Eu particularmente costumo utilizar mais as classes CL_ABAP_REGEX
e CL_ABAP_MATCHER. Acredito que minha preferência por este
modo é por estar muito mais próximo de outras linguagens, além de
me permitir mais flexibilidade. Veja só o exemplo abaixo:
1 DATA: regex TYPE REF TO cl_abap_regex,
2 matcher TYPE REF TO cl_abap_matcher,
3
4 pattern TYPE STRING,
5 phrase TYPE STRING.
6
7 pattern = 'Bar8'.
8 phrase = 'Bar8 o Blog do Desenvolvedor Moderno'.
9
10 CREATE OBJECT REGEX
11 EXPORTING
12 pattern = pattern
13 ignore_case = abap_true.
14
15 * Configurando o Matcher
Atenção! Esse modo está disponível apenas a partir da release ABAP 6.40
Uma forma fácil para apoiar os seus regex, a SAP disponibiliza um
programa para ajudar no estudos, basta acessar DEMO_REGEX_TOY.
Você deverá ter algo assim:
[Link] 13/17
2017627 Regex — Como não se apaixonar? – Bar8
Have fun!
Conclusão
Esta conclusão é exclusivamente para você, que ainda está em dúvida
sobre o Regex ser um dos recursos mais incríveis disponíveis no
desenvolvimento de software:
• Regex, como vimos, está presente em todas as linguagens de
programação que você puder imaginar, o que o torna uma
ferramenta extremamente flexível e de fácil reutilização;
• Regex lhe torna diferentão da maioria dos desenvolvedores que
para buscar uma expressão ficam quebrando a cabeça com
funções String;
• Menos código e, como resultado, mais tempo.
E ai ficou alguma dúvida ou quer enviar uma sugestão? Se sim, você
pode fazer isso comentando aqui no Medium, ou utilizar o grupo de
ABAP no #slack, lá você poderá ter contato não comigo, mas com
diversos outros desenvolvedores muito bons! O endereço no slack é:
[Link].
#Bar8Indica
[Link] 14/17