O documento discute expressões regulares (regex), mencionando que: 1) Embora regex sejam aceitas por quase todas as bibliotecas, na verdade não são expressões regulares; 2) São difíceis de entender e fáceis de errar; 3) Apesar disso, são extremamente compactas.
4. Verifica se número é primo
Isso não é uma expressão regular
(mas é aceito por quase todas bibliotecas regex)
5. Verifica se número é primo
Isso não é uma expressão regular
(mas é aceito por quase todas bibliotecas regex)
É difícil de entender
6. Verifica se número é primo
Isso não é uma expressão regular
(mas é aceito por quase todas bibliotecas regex)
É difícil de entender
É fácil de errar
7. Verifica se número é primo
Isso não é uma expressão regular
(mas é aceito por quase todas bibliotecas regex)
É difícil de entender
É fácil de errar
É extremamente compacta
8. Verifica se número é primo
Isso não é uma expressão regular
(mas é aceito por quase todas bibliotecas regex)
É difícil de entender
É fácil de errar
É extremamente compacta
Na verdade, checa se número não é primo
9. Histórico
Conceito matemático introduzido na década de 50
SNOBOL implementou pattern matching, mas não
expressões regulares
Ken Thompson introduzir expressões regulares no
editor QED, depois ed (Unix), e finalmente grep
(abreviação do comando g/re/p do ed)
Padronizado pelo POSIX
Repadronizado pelo Perl e Tcl (baseado em biblioteca
de Henry Spencer)
Biblioteca PCRE (Philip Hazel)
10. Para que servem Regex?
Verificar se um determinado padrão ocorre em um
texto
Verificar se um determinado padrão não ocorre em
um texto
Localizar as ocorrências de um padrão
Obter as ocorrências de um padrão
Obter partes das ocorrências de um padrão
Substituir ocorrências de um padrão por outro texto,
possivelmente usando partes da ocorrência
Dividir texto de acordo com um padrão
11. Exemplos
Acha linhas com configurações:
grep "^ *[^# ]" php.ini
Acha linhas que não estejam em branco:
grep –v "^$" .profile
Índice de todas palavras em um texto:
[w.start() for w in re.finditer(r'bw', text)]
Todas palavras de um texto:
@words = $text =~ /w+/
Dia, mês e ano de uma data:
($d, $m, $a) = text =~ /(dd)/(dd)/(d{4})/
Remove espaços do fim da linha:
sed -p'' -e 's/ *$//‘
Divide linha em palavras e símbolos
text split """bs*|s*b"""
12. Expressões Regulares
Descrevem Linguagens Regulares
Mesmo poder expressivo de Gramáticas Regulares
Mesmas linguagens aceitas por Autômatos Finitos
Determinísticos
Livres de Contexto
Exemplo de linguagem não regular:
Número de b depende do número de a: anbn
14. Dois switches e um loop
// Texto termina em n?
int state = 0;
while(ch = getc()) {
switch(state) {
case 0: switch(ch) {
case 'n': state = 1; break;
default : break;
}
case 1: switch(ch) {
case 'n': break;
default : state = 0; break;
}
}
}
return state == 1;
15. Estrutura de uma Regex
Composta de:
Um caracter (literal)
Ou nada (string vazia)
Ou uma composição de uma ou duas outras regex
16. Operações de Composição
Da maior precedência para a menor:
Repetição (kleene star): r*
Concatenação: r1 r2
Alternativa: r1 | r2
Todas expressões regulares podem ser compostas a
partir desses elementos
Muitas regex não podem ser compostas só com esses
elementos
17. Tipos de Regex
POSIX Basic Regex (grep)
POSIX Extended Regex (grep –E)
Preg (Perl regex)
PCRE (Perl Compatible(*) Regular Expression)
(*) Só que não
Etc... (cada biblioteca tem suas particularidades)
18. Regex Compilado vs JIT
Compilar um regex transforma a string representando
o regex em uma estrutura de dados otimizada para seu
uso
Disponível com Java, Perl, Python, Ruby
Regex Just In Time recompilam a expressão todas as
vezes, para diminuir a cerimônia de seu uso
Disponível com Java(*), Perl, PHP, Python, Ruby
(*) Somente para alguns usos
19. Outras operações de Composição
Qualquer caracter: .
Qualquer um de um conjunto: [r1r2-r3]
Qualquer um não em um conjunto: [^r1r2]
Classes de caracteres: [[:alpha:]], w,
Negação de classes: [^[:alpha:]], W
Classes POSIX: p{Upper}, P{InGreek}
Zero ou um: r?
Um ou mais: r+
Entre n e m repetições: r{n, m}
20. Classes úteis
[:alnum:]
w – inclui sublinhado (não palavras como W)
[:alpha:]
[:blank:]
[:cntrl:]
[:digit] ou d (não dígito como D)
[:graph:]
[:lower:]
[:print:]
[:punct:]
[:space:] ou s (não espaço como S)
[:upper:]
[:xdigit:]
21. Greediness
As expressões r* e r+ retornam a maior quantidade
possível de caracteres que satisfaçam a expressão
Elas são greedy – gananciosas
Algumas bibliotecas suportam relutância:
r*? e r+?
Elas retornam a menor quantidade possível de
caracteres que satisfaçam a expressão
Em alguns casos, a performance das repetições
relutantes é muito superior
22. Relembrando Precedência
Lembrando a precedência: repetição, concatenação e
alternativa
Textos que satisfazem a expressão ab*|cd:
a
ab
abb
cd
Os textos abab e acd não satisfazem a expressão
23. Agrupamento
POSIX Basic Regular Expression: ( e )
Todo o resto: ( e )
Grupos também capturam o conteúdo, e podem ser
extraídos separadamente ou usados na substituição
Sem captura(*): (?:r)
(*) as partes de uma ocorrência correspondentes a
expressões dentro de parênteses são retornadas como
grupos ou subgrupos
24. Contexto
Eu falei que expressões regulares são linguagens sem
contexto
Mas esses “contextos” são válidos, pois podem ser
representados como estados
Âncoras:
Início do texto ou de uma linha: ^
Fim do texto ou de uma linha: $
Borda de palavras: b ou < e > (POSIX BRE)
Look-ahead: (?=r)
Look-behind: (?<=r)
Negações: (?!r) e (?<!r)
25. Contexto de verdade
Não suportados por expressões regulares
Suportados por quase todas bibliotecas regex
Podem levar a tempos exponenciais
Back references: n (para n de 1 a 9)
26. Alterações de Comportamento
Formato:
Ativa/Desativa: (?idmsux-idmsux)
Somente para o subgrupo: (?idmsux-idmsux:r)
Flags:
Case insensitive: i
Unix new lines: d
Multiline: m
“.” pega new lines: s
Unicode-aware: u
Comentários: x
27. Escaping (citando caracteres)
PCRE:
antes de símbolos cita o símbolo
antes de letras tem tem significado especial
POSIX Basic RE: uma zona – consulte o manual
Citando um grupo de caracters:
Qgrupo de caracteresE
36. Explicando Números Primos
(?x) # Dado uma sequência de dígitos 1, aceita se o
# tamanho da sequência não for um número primo
# Primeiro caso, números menores que 2
^ # Início da string
1? # 0 ou 1 ocorrênicas do dígito 1
$ # Fim da String
| # Segundo caso, números maiores ou igual a 2
# Verifica se a string pode ser reduzida a
# XX...X, onde X é uma string de tamanho fixo
# com dois ou mais dígitos 1
^ # Início da string
( # Início do primeiro subgrupo -- o “X” da questão
11+? # Sequência de dois ou mais dígitos 1
# A sequência acima é relutante por questões de performance
) # Fim da sequência
1+ # Uma ou mais (novas) ocorrências do subgrupo 1
$ # Fim da string
39. Moral da História
Coisas que não são regex as vezes podem ser resolvidas
com regex
Coisas que são regex as vezes não valem a pena serem
resolvidas com regex
Algumas coisas não são regex e não são resolvidas com
regex
Resolver com código expressões regulares simples é
muito mais complicado do que as pessoas assumem
Não usem regex com xml!
40. Criando e Testando Regex
RegexBuddy (produto comercial): o melhor de todos
DFA/Regex: http://osteele.com/tools/reanimator/
.Net: http://www.nregex.com/nregex/default.aspx
Java: http://www.myregexp.com/
JavaScript: http://www.regexpal.com/
Perl: http://www.regextester.com/ (tb PHP, POSIX)
PHP: http://regex.larsolavtorvik.com/ (tb Javascript)
Python: http://www.pythonregex.com/
Ruby: http://www.rubular.com/