Expressões Regulares: Guia Completo

Expressões Regulares: Guia Completo Expressões Regulares: Guia Completo
	
< > Input
Python
import re
Copied

Este caderno foi traduzido automaticamente para torná-lo acessível a mais pessoas, por favor me avise se você vir algum erro de digitação..

Métodoslink image 71

Localizarlink image 72

Com o método findall(), podemos encontrar todas as correspondências de um padrão em uma string.

	
< > Input
Python
string = "Hola, soy un string"
print(re.findall("Hola, soy", string))
Copied
>_ Output
			
['Hola, soy']

Pesquisalink image 73

Mas se quisermos encontrar a posição em que um padrão está localizado, podemos usar o método search() para procurar um padrão em uma string. Esse método retorna um objeto Match se encontrar uma correspondência, caso contrário, retorna None.

	
< > Input
Python
print(re.search("soy", string))
Copied
>_ Output
			
&lt;re.Match object; span=(6, 9), match='soy'&gt;

Correspondêncialink image 74

Também podemos usar o método match() que procura o padrão **no início** da string.

	
< > Input
Python
print(re.match("Hola", string))
print(re.match("soy", string))
Copied
>_ Output
			
&lt;re.Match object; span=(0, 4), match='Hola'&gt;
None

Spanlink image 75

Se quisermos obter a posição da correspondência, podemos usar o método span() que retorna uma tupla com a posição inicial e final da correspondência.

	
< > Input
Python
print(re.match("Hola", string).span())
Copied
>_ Output
			
(0, 4)

Grupolink image 76

Sabendo a posição da correspondência, podemos usar o método group() para obter a substring que corresponde ao padrão.

	
< > Input
Python
print(re.match("Hola", string).group())
Copied
>_ Output
			
Hola

Também poderíamos usar o início e o fim da correspondência para criar uma fatia da cadeia de caracteres.

	
< > Input
Python
start, end = re.match("Hola", string).span()
print(string[start:end])
Copied
>_ Output
			
Hola

Separaçãolink image 77

Com o método split(), podemos dividir uma string em uma lista de substrings usando um padrão como separador.

	
< > Input
Python
split = re.split("soy", string)
print(split)
Copied
>_ Output
			
['Hola, ', ' un string']

A frase foi dividida em duas cadeias de caracteres usando "I am" como separador.

Sublink image 78

Com o método sub(), podemos substituir todas as correspondências de um padrão por outra substring.

	
< > Input
Python
sub = re.sub("soy", "eres", string)
print(sub)
Copied
>_ Output
			
Hola, eres un string

Ele substituiu todas as correspondências de "I am" por "you are".

Padrõeslink image 79

O caractere .link image 80

Com o caractere ., podemos pesquisar qualquer caractere; qualquer caractere em nossa string será encontrado.

	
< > Input
Python
string = "Hola, soy un string"
print(re.findall(".", string))
Copied
>_ Output
			
['H', 'o', 'l', 'a', ',', ' ', 's', 'o', 'y', ' ', 'u', 'n', ' ', 's', 't', 'r', 'i', 'n', 'g']

Se, por exemplo, quisermos sequências de dois caracteres, faremos a busca com dois .s em uma linha.

	
< > Input
Python
string1 = "Hola, soy un string"
string2 = "Hola, soy un string2"
print(re.findall("..", string1))
print(re.findall("..", string2))
Copied
>_ Output
			
['Ho', 'la', ', ', 'so', 'y ', 'un', ' s', 'tr', 'in']
['Ho', 'la', ', ', 'so', 'y ', 'un', ' s', 'tr', 'in', 'g2']

Como podemos ver, string1 tem um número ímpar de caracteres, de modo que o último g não é usado, mas string2 tem um número par de caracteres, de modo que todos os caracteres são usados.

Vamos analisar isso de outra forma: vamos alterar cada sequência de três caracteres para um símbolo $.

	
< > Input
Python
print(string1)
print(re.sub("...", "$ ", string1))
Copied
>_ Output
			
Hola, soy un string
$ $ $ $ $ $ g

Imprimi dois espaços após cada $ para que você possa ver a alteração, e você pode ver como o último caractere não o converte.

As classes predefinidas e construídaslink image 81

Dígitolink image 82

Se quisermos encontrar os dígitos, precisaremos usar d.

	
< > Input
Python
string = "Hola, soy un string con 123 digitos"
print(re.findall("d", string))
Copied
>_ Output
			
['1', '2', '3']

Como antes, se, por exemplo, quisermos dois dígitos, colocamos d duas vezes.

	
< > Input
Python
print(re.findall("dd", string))
Copied
>_ Output
			
['12']

Cartalink image 83

Se quisermos encontrar letras, precisamos usar w. Palavra significa todas as letras de a a z, de A a Z, números de 0 a 9 e o _.

	
< > Input
Python
string = "Hola, soy un_string con, 123 digitos"
print(re.findall("w", string))
Copied
>_ Output
			
['H', 'o', 'l', 'a', 's', 'o', 'y', 'u', 'n', '_', 's', 't', 'r', 'i', 'n', 'g', 'c', 'o', 'n', '1', '2', '3', 'd', 'i', 'g', 'i', 't', 'o', 's']

Como podemos ver, ele usa tudo, exceto os espaços e a vírgula.

Espaçoslink image 84

Se quisermos encontrar espaços, precisamos de "espaços".

	
< > Input
Python
string = "Hola, soy un_string con, 123 digitos"
print(re.sub("s", "*", string))
Copied
>_ Output
			
Hola,*soy*un_string*con,*123*digitos

As expressões regulares tratam as quebras de linha como espaços.

	
< > Input
Python
string = """Hola, soy un string
con un salto de línea"""
print(re.sub("s", "*", string))
Copied
>_ Output
			
Hola,*soy*un*string**con*un*salto*de*línea

Rankslink image 85

Se quisermos pesquisar um intervalo, usaremos [], por exemplo, se quisermos os números de 4 a 8, usaremos

	
< > Input
Python
string = "1234567890"
print(re.findall("[4-8]", string))
Copied
>_ Output
			
['4', '5', '6', '7', '8']

Podemos ampliar o intervalo de pesquisa

	
< > Input
Python
string = "1234567890"
print(re.findall("[2-57-9]", string))
Copied
>_ Output
			
['2', '3', '4', '5', '7', '8', '9']

Se também quisermos encontrar um caractere específico, colocaremos o caractere seguido de ``.

	
< > Input
Python
string = "1234567890."
print(re.findall("[2-57-9.]", string))
Copied
>_ Output
			
['2', '3', '4', '5', '7', '8', '9', '.']

Colchete [ e colchete ]link image 86

Como vimos, se quisermos encontrar intervalos, usamos [], mas e se quisermos encontrar apenas o [ ou o ]? Para isso, temos que usar [] e []`.

	
< > Input
Python
string = "[1234567890]"
print(re.findall("[", string))
print(re.findall("]", string))
Copied
>_ Output
			
['[']
[']']

Os delimitadores +, *, ?, `?link image 87

Star * (nenhum ou todos)link image 88

O delimitador * indica que você deseja pesquisar nenhum ou todos eles, e não um a um como antes.

	
< > Input
Python
string = "Hola, soy un string con 12 123 digitos"
print(re.findall("d", string))
print(re.findall("d*", string))
Copied
>_ Output
			
['1', '2', '1', '2', '3']
['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '12', '', '123', '', '', '', '', '', '', '', '', '']

Como você pode ver, colocar o * encontrou todas as posições em que há zero caracteres ou todos os caracteres.

Plus + (um ou mais)link image 89

Com o delimitador +, você indica que deseja pesquisar um ou mais

	
< > Input
Python
string = "Hola, soy un string con 1 12 123 digitos"
print(re.findall("d+", string))
Copied
>_ Output
			
['1', '12', '123']

Opcional ? (zero ou um)link image 90

O delimitador ? indica que você deseja pesquisar zero ou um.

	
< > Input
Python
string = "Hola, soy un string con 1 12 123 digitos"
print(re.sub("d?", "-", string))
Copied
>_ Output
			
-H-o-l-a-,- -s-o-y- -u-n- -s-t-r-i-n-g- -c-o-n- -- --- ---- -d-i-g-i-t-o-s-

Contadoreslink image 91

Quando quisermos encontrar algo que apareça x vezes, usaremos os contadores entre chaves {}. Por exemplo, se quisermos encontrar uma sequência na qual haja pelo menos dois dígitos

	
< > Input
Python
string = "Hola, soy un string con 1 12 123 1234 1234digitos"
print(re.findall("d{2}", string))
Copied
>_ Output
			
['12', '12', '12', '34', '12', '34']

Como você pode ver, você encontrou as sequências 12 e 34.

Os contadores aceitam uma dimensão superior e inferior {{inf, sup}.

	
< > Input
Python
string = "Hola, soy un string con 1 12 123 1234 1234digitos"
print(re.findall("d{2,5}", string))
Copied
>_ Output
			
['12', '123', '1234', '1234']

Se nenhuma dimensão superior for definida, isso significa que você deseja pelo menos o número de elementos indicado, mas nenhum limite superior.

	
< > Input
Python
string = "Hola, soy un string con 1 12 123 1234 12345464168415641646451563416 digitos"
print(re.findall("d{2,}", string))
Copied
>_ Output
			
['12', '123', '1234', '12345464168415641646451563416']

Se quisermos usar a notação de dimensão superior e inferior, mas quisermos um número fixo, teremos que colocar esse número em ambas as dimensões.

	
< > Input
Python
string = "Hola, soy un string con 1 12 123 1234 12345464168415641646451563416 digitos"
print(re.findall("d{2,3}", string))
Copied
>_ Output
			
['12', '123', '123', '123', '454', '641', '684', '156', '416', '464', '515', '634', '16']

Classeslink image 92

Você pode criar classes usando colchetes []. Na verdade, vimos que isso era para intervalos, mas, depois de definir o que deseja dentro deles, você pode considerá-lo como uma classe e operar com o [].

Por exemplo, suponha que tenhamos um número de telefone, que pode ser fornecido de uma das seguintes maneiras

  • 666-66-66-66
  • 666-666-666
  • 666 666 666
  • 666 66 66 66
  • 666666666

Há muitas maneiras de fornecer um número, portanto, vamos ver como criar uma classe para definir o delimitador.

Primeiro, pediremos a ele que encontre todas as sequências de números em que haja pelo menos dois números.

	
< > Input
Python
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} --&gt;", re.findall("d{2,}", string1))
print(f"string2: {string2} --&gt;", re.findall("d{2,}", string2))
print(f"string3: {string3} --&gt;", re.findall("d{2,}", string3))
print(f"string4: {string4} --&gt;", re.findall("d{2,}", string4))
print(f"string5: {string5} --&gt;", re.findall("d{2,}", string5))
Copied
>_ Output
			
string1: 666-66-66-66 --&gt; ['666', '66', '66', '66']
string2: 666-666-666 --&gt; ['666', '666', '666']
string3: 666 66 66 66 --&gt; ['666', '66', '66', '66']
string4: 666 666 666 --&gt; ['666', '666', '666']
string5: 666666666 --&gt; ['666666666']

Agora, definimos o separador a ser encontrado como um - ou um espaço.

	
< > Input
Python
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} --&gt;", re.findall("[-s]", string1))
print(f"string2: {string2} --&gt;", re.findall("[-s]", string2))
print(f"string3: {string3} --&gt;", re.findall("[-s]", string3))
print(f"string4: {string4} --&gt;", re.findall("[-s]", string4))
print(f"string5: {string5} --&gt;", re.findall("[-s]", string5))
Copied
>_ Output
			
string1: 666-66-66-66 --&gt; ['-', '-', '-']
string2: 666-666-666 --&gt; ['-', '-']
string3: 666 66 66 66 --&gt; [' ', ' ', ' ']
string4: 666 666 666 --&gt; [' ', ' ']
string5: 666666666 --&gt; []

Como você pode ver na última string, ela não foi encontrada, então adicionamos um ? para encontrar quando há zero ou um.

	
< > Input
Python
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} --&gt;", re.findall("[-s]?", string1))
print(f"string2: {string2} --&gt;", re.findall("[-s]?", string2))
print(f"string3: {string3} --&gt;", re.findall("[-s]?", string3))
print(f"string4: {string4} --&gt;", re.findall("[-s]?", string4))
print(f"string5: {string5} --&gt;", re.findall("[-s]?", string5))
Copied
>_ Output
			
string1: 666-66-66-66 --&gt; ['', '', '', '-', '', '', '-', '', '', '-', '', '', '']
string2: 666-666-666 --&gt; ['', '', '', '-', '', '', '', '-', '', '', '', '']
string3: 666 66 66 66 --&gt; ['', '', '', ' ', '', '', ' ', '', '', ' ', '', '', '']
string4: 666 666 666 --&gt; ['', '', '', ' ', '', '', '', ' ', '', '', '', '']
string5: 666666666 --&gt; ['', '', '', '', '', '', '', '', '', '']

Agora estamos procurando que tudo esteja junto

	
< > Input
Python
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string1))
print(f"string2: {string2} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string2))
print(f"string3: {string3} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string3))
print(f"string4: {string4} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string4))
print(f"string5: {string5} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?", string5))
Copied
>_ Output
			
string1: 666-66-66-66 --&gt; ['666-66-66-66']
string2: 666-666-666 --&gt; []
string3: 666 66 66 66 --&gt; ['666 66 66 66']
string4: 666 666 666 --&gt; []
string5: 666666666 --&gt; ['666666666']

Como podemos ver em string2 e string4, ele não encontra nada. Definimos o filtro [\d{2,}[\s]? 4 vezes, ou seja, queremos uma sequência de pelo menos dois números, seguida por zero ou um hífen ou separador de espaço que se repita 4 vezes. Mas na última sequência não há necessidade do [\d{2,}[\s]?, pois ele nunca terminará um número com um espaço ou um hífen.

	
< > Input
Python
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string1))
print(f"string2: {string2} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string2))
print(f"string3: {string3} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string3))
print(f"string4: {string4} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string4))
print(f"string5: {string5} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d{2,}", string5))
Copied
>_ Output
			
string1: 666-66-66-66 --&gt; ['666-66-66-66']
string2: 666-666-666 --&gt; []
string3: 666 66 66 66 --&gt; ['666 66 66 66']
string4: 666 666 666 --&gt; []
string5: 666666666 --&gt; ['666666666']

Ainda não foi encontrado para string2 e string4. Isso ocorre porque a última coisa no filtro é um d{2,}, ou seja, após o terceiro separador, esperamos pelo menos dois números, mas isso não acontece em string2 e string4, então colocamos o seguinte

	
< > Input
Python
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string1))
print(f"string2: {string2} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string2))
print(f"string3: {string3} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string3))
print(f"string4: {string4} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string4))
print(f"string5: {string5} --&gt;", re.findall("d{2,}[-s]?d{2,}[-s]?d{2,}[-s]?d*", string5))
Copied
>_ Output
			
string1: 666-66-66-66 --&gt; ['666-66-66-66']
string2: 666-666-666 --&gt; ['666-666-666']
string3: 666 66 66 66 --&gt; ['666 66 66 66']
string4: 666 666 666 --&gt; ['666 666 666']
string5: 666666666 --&gt; ['666666666']

O delimitador ? como um delimitador rápidolink image 93

O exemplo acima pode ser filtrado usando d+?[- ].

	
< > Input
Python
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} --&gt;", re.findall("d+?[- ]", string1))
print(f"string2: {string2} --&gt;", re.findall("d+?[- ]", string2))
print(f"string3: {string3} --&gt;", re.findall("d+?[- ]", string3))
print(f"string4: {string4} --&gt;", re.findall("d+?[- ]", string4))
print(f"string5: {string5} --&gt;", re.findall("d+?[- ]", string5))
Copied
>_ Output
			
string1: 666-66-66-66 --&gt; ['666-', '66-', '66-']
string2: 666-666-666 --&gt; ['666-', '666-']
string3: 666 66 66 66 --&gt; ['666 ', '66 ', '66 ']
string4: 666 666 666 --&gt; ['666 ', '666 ']
string5: 666666666 --&gt; []

Sem o delimitador ?, teríamos \d+[- ], o que significa uma sequência de um ou mais números seguidos por um espaço ou hífen. Mas o que o delimitador ? faz é tornar essa busca mais rápida

O negadorlink image 94

Anteriormente, vimos que com d encontramos dígitos, portanto, com D encontramos tudo o que não é dígito.

	
< > Input
Python
string1 = "E3s4t6e e1s2t3r5i6n7g8 t9i0e4n2e1 d4i5g7i9t0o5s2"
print(re.findall("D", string1))
Copied
>_ Output
			
['E', 's', 't', 'e', ' ', 'e', 's', 't', 'r', 'i', 'n', 'g', ' ', 't', 'i', 'e', 'n', 'e', ' ', 'd', 'i', 'g', 'i', 't', 'o', 's']

O mesmo vale para as letras: se você digitar W, ele encontrará tudo o que não for uma letra.

	
< > Input
Python
string1 = "Letras ab27_ no letras ,.:;´ç"
print(re.findall("W", string1))
Copied
>_ Output
			
[' ', ' ', ' ', ' ', ',', '.', ':', ';', '´']

Se colocarmos S, encontraremos tudo o que não for espaço

	
< > Input
Python
print(re.findall("S", string1))
Copied
>_ Output
			
['L', 'e', 't', 'r', 'a', 's', 'a', 'b', '2', '7', '_', 'n', 'o', 'l', 'e', 't', 'r', 'a', 's', ',', '.', ':', ';', '´', 'ç']

Mas, caso tenhamos uma classe ou outra coisa, podemos negá-la com ^.

	
< > Input
Python
string1 = "1234567890"
print(re.findall("[^5-9]", string1))
Copied
>_ Output
			
['1', '2', '3', '4', '0']

Voltando ao exemplo anterior dos números de telefone, podemos filtrá-los da seguinte forma

	
< > Input
Python
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} --&gt;", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string1))
print(f"string2: {string2} --&gt;", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string2))
print(f"string3: {string3} --&gt;", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string3))
print(f"string4: {string4} --&gt;", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string4))
print(f"string5: {string5} --&gt;", re.findall("d{2,}D?d{2,}D?d{2,}D?d*", string5))
string5 = "666 666 666"
Copied
>_ Output
			
string1: 666-66-66-66 --&gt; ['666-66-66-66']
string2: 666-666-666 --&gt; ['666-666-666']
string3: 666 66 66 66 --&gt; ['666 66 66 66']
string4: 666 666 666 --&gt; ['666 666 666']
string5: 666666666 --&gt; ['666666666']

O que estamos fazendo é solicitar sequências de pelo menos dois dígitos seguidos de um ou nenhum não-dígito.

O início ^ e o final da linha $.link image 95

Com ^, podemos pesquisar o início de uma linha, por exemplo, se quisermos encontrar um dígito que esteja apenas no início de uma linha.

	
< > Input
Python
string1 = "linea 1"
string2 = "2ª linea"
print(re.findall("^d", string1))
print(re.findall("^d", string2))
Copied
>_ Output
			
[]
['2']

Como você pode ver, há apenas um dígito no início da linha em string2.

Da mesma forma, o final de uma linha pode ser encontrado com $. Se quisermos encontrar um dígito apenas no final de uma linha

	
< > Input
Python
string1 = "linea 1"
string2 = "2ª linea"
print(re.findall("d$", string1))
print(re.findall("d$", string2))
Copied
>_ Output
			
['1']
[]

Isso só ocorre em string1.

Exemplos práticoslink image 96

Registroslink image 97

Se no registro a seguir quisermos encontrar apenas os WARNs

	
< > Input
Python
log = """[LOG ENTRY] [ERROR] The system is unstable
[LOG ENTRY] [WARN] The system may be down
[LOG ENTRY] [WARN] Microsoft just bought Github
[LOG DATA] [LOG] Everything is OK
[LOG ENTRY] [LOG] [user:@beco] Logged in
[LOG ENTRY] [LOG] [user:@beco] Clicked here
[LOG DATA] [LOG] [user:@celismx] Did something
[LOG ENTRY] [LOG] [user:@beco] Rated the app
[LOG ENTRY] [LOG] [user:@beco] Logged out
[LOG LINE] [LOG] [user:@celismx] Logged in"""
result = re.findall("[LOG.*[WARN].*", log)
result
Copied
>_ Output
			
['[LOG ENTRY] [WARN] The system may be down',
'[LOG ENTRY] [WARN] Microsoft just bought Github']

Número de telefonelink image 98

Dentro de um número, podemos encontrar letras como e para ramal, # também para ramal ou p para fazer uma pausa se um computador ligar. Também podemos encontrar o + para indicar um prefixo de país e separadores como espaços, -, ., ., ., ., ., ., ., ., ., ., ..

	
< > Input
Python
tel = """555658
56-58-11
56.58.11
56.78-98
65 09 87
76y87r98
45y78-56
78.87 65
78 54-56
+521565811
58-11-11#246
55256048p123
55256048e123"""
result = re.findall("+?d{2,3}[^da-zA-Z ]?d{2,3}[^da-zA-Z ]?d{2,3}[#pe]?d*", tel)
result
Copied
>_ Output
			
['555658',
'56-58-11',
'56.58.11',
'56.78-98',
'65 09 87',
'78.87 65',
'78 54-56',
'+521565811',
'58-11-11#246',
'55256048p123',
'55256048e123']

Vamos explicar

  • +?: começando com o caractere + e contendo zero ou um
  • d{2,3}: a ser seguido por 2 a 3 dígitos
  • Em seguida, pode haver zero ou um caractere que não seja um dígito, nem uma letra de a a z, nem uma letra de A a Z, nem uma quebra de linha.
  • d{2,3}: a ser seguido por 2 a 3 dígitos
  • Em seguida, pode haver zero ou um caractere que não seja um dígito, nem uma letra de a a z, nem uma letra de A a Z, nem uma quebra de linha.
  • d{2,3}: a ser seguido por 2 a 3 dígitos
  • [#pe]?: então pode haver zero ou um caractere #, ou p, ou e.
  • Por fim, que haja zero ou todos os números.

URLslink image 99

	
< > Input
Python
urls = """url: https://www.instagram.com/p/BXB4zsUlW5Z/?taken-by=beco.mx
url: http://instagram.com/p/blablablah
url: http://itam.mx/test
http://instagram.com/p/blablablah
https://www.vanguarsoft.com.ve
http://platzi.com
https://traetelo.net
https://traetelo.net/images archivo.jsp
url: https://subdominio.traetelo.net
url: https://www.instagram.com/p/BXB4zsUlW5Z/?taken-by=beco.mx
url: http://instagram.com/p/blablablah
url: http://itam.mx/test
http://instagram.com/p/blablablah
https://www.google.com.co/
https://sub.dominio.de.alguien.com/archivo.html
https://en.wikipedia.org/wiki/.org
https://cdn-microsoft.org/image/seixo2t9sjl_22.jpg
https://hola.pizza
https://platzi.com/clases/1301-expresiones-regulares/11860-urls9102/ clase
https://api.giphy.com/v1/gifs/search?q=Rick and Morty&amp;limit=10&amp;api_key=DG3hItPp5HIRNC0nit3AOR7eQZAe
http://localhost:3000/something?color1=red&amp;color2=blue
http://localhost:3000/display/post?size=small
http://localhost:3000/?name=satyam
http://localhost:3000/scanned?orderid=234
http://localhost:3000/getUsers?userId=12354411&amp;name=Billy
http://localhost:3000/getUsers?userId=12354411
http://localhost:3000/search?city=Barcelona
www.sitiodeejemplo.net/pagina.php?nombredevalor1=valor1&amp;nombredevalor2=valor2"""
result = re.findall("https?://[w-.]+.w{2,6}/?S*", urls)
result
Copied
>_ Output
			
['https://www.instagram.com/p/BXB4zsUlW5Z/?taken-by=beco.mx',
'http://instagram.com/p/blablablah',
'http://itam.mx/test',
'http://instagram.com/p/blablablah',
'https://www.vanguarsoft.com.ve',
'http://platzi.com',
'https://traetelo.net',
'https://traetelo.net/images',
'https://subdominio.traetelo.net',
'https://www.instagram.com/p/BXB4zsUlW5Z/?taken-by=beco.mx',
'http://instagram.com/p/blablablah',
'http://itam.mx/test',
'http://instagram.com/p/blablablah',
'https://www.google.com.co/',
'https://sub.dominio.de.alguien.com/archivo.html',
'https://en.wikipedia.org/wiki/.org',
'https://cdn-microsoft.org/image/seixo2t9sjl_22.jpg',
'https://hola.pizza',
'https://platzi.com/clases/1301-expresiones-regulares/11860-urls9102/',
'https://api.giphy.com/v1/gifs/search?q=Rick']

Vamos explicar

  • http: queremos que ele comece com http.
  • s?: Então pode ou não haver um s.
  • :\/: seguido por ://
  • `[+]: seguido de uma ou mais letras, traços ou pontos
  • Então, um ponto
  • w{2,6}: Entre 2 e 6 letras para o tld
  • \/?: seguido por zero ou um /
  • Nenhum ou tudo que não seja um espaço.

E-mailslink image 100

	
< > Input
Python
mails = """esto.es_un.mail@mail.com
esto.es_un.mail+complejo@mail.com
dominio.com
rodrigo.jimenez@yahoo.com.mx
ruben@starbucks.com
esto_no$es_email@dominio.com
no_se_de_internet3@hotmail.com"""
result = re.findall("[w._]{5,30}+?[w._]{0,10}@[w.-]{2,}.w{2,6}", mails)
result
Copied
>_ Output
			
['esto.es_un.mail@mail.com',
'esto.es_un.mail+complejo@mail.com',
'rodrigo.jimenez@yahoo.com.mx',
'ruben@starbucks.com',
'es_email@dominio.com',
'no_se_de_internet3@hotmail.com']

Vamos explicar

  • [\w\._]{5,30}: Queremos que empiece por entre 5 y 30 (que es lo mínimo y máximo que admite gmail) letras, puntos o barras bajas
  • \+?: Seguido de cero o un +
  • [\w\._]{0,10}: A continuación entre 0 y 10 letras, puntos o barras bajas
  • @: La @
  • [\w\.-]{2,}: Entre 2 e infinitas letras, puntos y guiones (dominio)
  • \.: Seguido de un .
  • \w{2,6}: Y por último, entre 2 y 6 letras para el tld
  • [\w\._]{5,30}: queremos que ele comece com um número entre 5 e 30 (que é o mínimo e o máximo que o gmail suporta) letras, pontos ou sublinhados.
  • \+?: Seguido por um zero ou um +.
  • [\w\._]{0,10}: Então, entre 0 e 10 letras, pontos ou barras
  • @: O @
  • [\w\.-]{2,}: Entre 2 e infinitas letras, pontos e hífens (domínio)
  • \.: seguido de um '.
  • \w{2,6}: E, finalmente, entre 2 e 6 letras para o tld

Localizaçõeslink image 101

Há duas maneiras possíveis de fornecer locais, portanto, examinaremos ambas

	
< > Input
Python
loc = """-99.205646,19.429707,2275.10
-99.205581, 19.429652,2275.10
-99.204654,19.428952,2275.58"""
result = re.findall("-?d{1,3}.d{1,6},s?-?d{1,3}.d{1,6},.*", loc)
result
Copied
>_ Output
			
['-99.205646,19.429707,2275.10',
'-99.205581, 19.429652,2275.10',
'-99.204654,19.428952,2275.58']

Vamos explicar

  • Queremos que ele comece com zero ou um sinal de menos.
  • Seguido de um a três números
  • Então, um ponto
  • d{1,6}: Depois de um a seis números
  • ,: Then a ,: Then a ,: Then a ,: Then a ,: Then a ,
  • s?: Após zero ou um espaço
  • `-?: Zero ou um sinal de menos
  • ``: Então, entre um e três números
  • Então, um ponto
  • Seguido de um a seis números
  • ,: depois uma vírgula
  • Finalmente, nenhum ou todos os tipos de caracteres
	
< > Input
Python
loc = """-99 12' 34.08"W, 19 34' 56.98"N
-34 54' 32.00"E, -3 21' 67.00"S"""
result = re.findall("-?d{1,3}sd{1,2}'sd{1,2}.d{2,2}"[WE],s?-?d{1,3}sd{1,2}'sd{1,2}.d{2,2}"[SN]", loc)
result
Copied
>_ Output
			
['-99 12' 34.08"W, 19 34' 56.98"N', '-34 54' 32.00"E, -3 21' 67.00"S']
	
< > Input
Python
print(result[0])
print(result[1])
Copied
>_ Output
			
-99 12' 34.08"W, 19 34' 56.98"N
-34 54' 32.00"E, -3 21' 67.00"S

Vamos explicar

  • Queremos que ele comece com zero ou um sinal de menos.
  • Seguido de um a três números
  • s: Em seguida, um espaço
  • d{1,2}: Segmento de um a dois números
  • ': Then a ': Then a ': Then a ': Then a ': Then a '
  • Seguido de um espaço
  • ``: Então, entre um e dois números
  • Após um ponto
  • d{2,2}: seguido por dois números
  • ": then a ": then a ": then a ": then a ".
  • [WE]: Em seguida, a letra W ou a letra E.
  • ,: Após uma vírgula
  • Seguido por um zero ou um espaço
  • `-?: Então, zero ou um sinal de menos
  • ``: Então, entre um e três números
  • Seguido de um espaço
  • ``: Então, entre um e dois números
  • ': Then a ': After a '
  • s: Em seguida, um espaço
  • d2`: Então, entre um e dois números
  • seguido de um ponto final
  • d{2,2}: Então, dois números
  • ": Seguido por ".
  • [SN]: E, finalmente, a letra S ou a letra N.

Nomeslink image 102

	
< > Input
Python
nombres = """Camilo Sarmiento Gálvez
Alejandro Pliego Abasto
Milagros Reyes Japón
Samuel París Arrabal
Juan Pablo Tafalla
Axel Gálvez Velázquez
Óscar Montreal Aparicio
Jacobo Pozo Tassis
Guillermo Ordóñez Espiga
Eduardo Pousa Curbelo
Ivanna Bienvenida Kevin
Ada Tasis López
Luciana Sáenz García
Florencia Sainz Márquz
Catarina Cazalla Lombarda
Paloma Gallo Perro
Margarita Quesada Florez
Vicente Fox Quesada
Iris Graciani
Asunción Carballar
Constanza Muñoz
Manuel Andres García Márquez"""
result = re.findall("[A-ZÁÉÍÓÚ][a-záéíóú]+s[A-ZÁÉÍÓÚ][a-záéíóú]+s[A-ZÁÉÍÓÚ][a-záéíóú]+", nombres)
result
Copied
>_ Output
			
['Camilo Sarmiento Gálvez',
'Alejandro Pliego Abasto',
'Milagros Reyes Japón',
'Samuel París Arrabal',
'Juan Pablo Tafalla',
'Axel Gálvez Velázquez',
'Óscar Montreal Aparicio',
'Jacobo Pozo Tassis',
'Espiga Eduardo Pousa',
'Curbelo Ivanna Bienvenida',
'Kevin Ada Tasis',
'López Luciana Sáenz',
'García Florencia Sainz',
'Márquz Catarina Cazalla',
'Lombarda Paloma Gallo',
'Perro Margarita Quesada',
'Florez Vicente Fox',
'Quesada Iris Graciani',
'Asunción Carballar Constanza',
'Manuel Andres García']

Vamos explicar

  • [A-ZÁÉÍÓÚ]: queremos que ele comece com uma letra maiúscula, incluindo acentos.
  • [a-záééíóú]+: seguido de uma ou mais letras minúsculas, entre espaços
  • Seguido de um espaço
  • [A-ZÁÉÍÓÚ]: seguido de uma letra maiúscula, incluindo acentos
  • [a-záééíóú]+: seguido de uma ou mais letras minúsculas, entre espaços
  • Seguido de um espaço
  • [A-ZÁÉÍÓÚ]: seguido de uma letra maiúscula, incluindo acentos
  • [a-záééíóú]+: seguido de uma ou mais letras minúsculas, entre espaços

Pesquisar e substituirlink image 103

Faremos o download de um arquivo com vários filmes históricos.

	
< > Input
Python
# download file from url
import urllib.request
url = "https://static.platzi.com/media/tmp/class-files/github/moviedemo/moviedemo-master/movies.dat"
urllib.request.urlretrieve(url, "movies.dat")
Copied
>_ Output
			
---------------------------------------------------------------------------HTTPError Traceback (most recent call last)Cell In[43], line 4
2 import urllib.request
3 url = "https://static.platzi.com/media/tmp/class-files/github/moviedemo/moviedemo-master/movies.dat"
----&gt; 4 urllib.request.urlretrieve(url, "movies.dat")
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:241, in urlretrieve(url, filename, reporthook, data)
224 """
225 Retrieve a URL into a temporary location on disk.
226
(...)
237 data file as well as the resulting HTTPMessage object.
238 """
239 url_type, path = _splittype(url)
--&gt; 241 with contextlib.closing(urlopen(url, data)) as fp:
242 headers = fp.info()
244 # Just return the local path and the "headers" for file://
245 # URLs. No sense in performing a copy unless requested.
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:216, in urlopen(url, data, timeout, cafile, capath, cadefault, context)
214 else:
215 opener = _opener
--&gt; 216 return opener.open(url, data, timeout)
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:525, in OpenerDirector.open(self, fullurl, data, timeout)
523 for processor in self.process_response.get(protocol, []):
524 meth = getattr(processor, meth_name)
--&gt; 525 response = meth(req, response)
527 return response
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:634, in HTTPErrorProcessor.http_response(self, request, response)
631 # According to RFC 2616, "2xx" code indicates that the client's
632 # request was successfully received, understood, and accepted.
633 if not (200 &lt;= code &lt; 300):
--&gt; 634 response = self.parent.error(
635 'http', request, response, code, msg, hdrs)
637 return response
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:563, in OpenerDirector.error(self, proto, *args)
561 if http_err:
562 args = (dict, 'default', 'http_error_default') + orig_args
--&gt; 563 return self._call_chain(*args)
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:496, in OpenerDirector._call_chain(self, chain, kind, meth_name, *args)
494 for handler in handlers:
495 func = getattr(handler, meth_name)
--&gt; 496 result = func(*args)
497 if result is not None:
498 return result
File ~/miniconda3/envs/mybase/lib/python3.11/urllib/request.py:643, in HTTPDefaultErrorHandler.http_error_default(self, req, fp, code, msg, hdrs)
642 def http_error_default(self, req, fp, code, msg, hdrs):
--&gt; 643 raise HTTPError(req.full_url, code, msg, hdrs, fp)
HTTPError: HTTP Error 403: Forbidden

Vamos imprimir as primeiras 10 linhas para analisá-las.

	
< > Input
Python
file = open("movies.dat", "r")
for i, line in enumerate(file):
print(line, end="")
if i == 10:
break
file.close()
Copied
>_ Output
			
1::Toy Story (1995)::Adventure|Animation|Children|Comedy|Fantasy
2::Jumanji (1995)::Adventure|Children|Fantasy
3::Grumpier Old Men (1995)::Comedy|Romance
4::Waiting to Exhale (1995)::Comedy|Drama|Romance
5::Father of the Bride Part II (1995)::Comedy
6::Heat (1995)::Action|Crime|Thriller
7::Sabrina (1995)::Comedy|Romance
8::Tom and Huck (1995)::Adventure|Children
9::Sudden Death (1995)::Action
10::GoldenEye (1995)::Action|Adventure|Thriller
11::American President, The (1995)::Comedy|Drama|Romance

Como você pode ver, temos um ID, seguido por ::, depois o nome do filme, entre parênteses o ano, seguido por :: e depois os gêneros separados por |.

Podemos fazer uma limpeza de arquivo muito fácil usando expressões regulares, as funções compile e match e o uso de agrupamento com parênteses. Ao agrupar, selecionamos as áreas do texto que queremos manter e, em seguida, trabalhamos com elas como quisermos.

	
< > Input
Python
pattern = re.compile(r"^d+::([ws:,().-'&amp;¡!/¿?ÁÉÍÓÚáéíóú+*$#°'"[]@·]+)s((d{4,4}))::(.*)$")
file = open("movies.dat", "r")
file_filtered = open("movies.csv", "w")
file_filtered.write("title,year,genders ")
sep = ";;"
for line in file:
result = re.match(pattern, line)
if result:
file_filtered.write(f"{result.group(1)}{sep}{result.group(2)}{sep}{result.group(3)} ")
else:
print(line, end="")
file.close()
file_filtered.close()
Copied

Vejamos o que fizemos: primeiro, definimos um padrão com o seguinte:

  • ^: Queremos que ele comece com o início da linha.
  • Próximo um ou mais números
  • ::: Seguido por ::
  • `((([\¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡: esse é o primeiro agrupamento, procuramos qualquer palavra, espaço ou caractere entre colchetes que apareça uma ou mais vezes.
  • s: depois um espaço
  • `: O fechamento de um parêntese
  • (4,4})`: Aqui está o segundo agrupamento, estamos procurando por quatro números.
  • Após o fechamento de um parêntese
  • ::: Then ::
  • (.*): o terceiro agrupamento, qualquer caractere que não ocorra nenhuma ou todas as vezes
  • $: Por último, o final da linha

Dentro do for, analisamos linha por linha se o padrão que definimos foi encontrado e, se for encontrado, escrevemos os três padrões no csv separados por sep, que, no nosso caso, definimos como ;;. Esse separador foi definido porque há títulos de filmes que têm ,s.

Lemos o csv com o Pandas.

	
< > Input
Python
import pandas as pd
df = pd.read_csv("movies.csv", sep=";;", engine="python")
df.head()
Copied
>_ Output
			
title,year,genders
Toy Story 1995 Adventure|Animation|Children|Comedy|Fantasy
Jumanji 1995 Adventure|Children|Fantasy
Grumpier Old Men 1995 Comedy|Romance
Waiting to Exhale 1995 Comedy|Drama|Romance
Father of the Bride Part II 1995 Comedy

Folha de dicaslink image 104

Aqui está um [cheatsheet] (https://images.maximofn.com/davechild_regular-expressions.pdf) com vários padrões

davechild_regular-expressions

Continuar lendo

Últimos posts -->

Você viu esses projetos?

Gymnasia

Gymnasia Gymnasia
React Native
Expo
TypeScript
FastAPI
Next.js
OpenAI
Anthropic

Aplicativo móvel de treino pessoal com assistente de IA, biblioteca de exercícios, acompanhamento de rotinas, dieta e medidas corporais

Horeca chatbot

Horeca chatbot Horeca chatbot
Python
LangChain
PostgreSQL
PGVector
React
Kubernetes
Docker
GitHub Actions

Chatbot conversacional para cozinheiros de hotéis e restaurantes. Um cozinheiro, gerente de cozinha ou serviço de quarto de um hotel ou restaurante pode falar com o chatbot para obter informações sobre receitas e menus. Mas também implementa agentes, com os quais pode editar ou criar novas receitas ou menus

Naviground

Naviground Naviground
Ver todos os projetos -->
>_ Disponível para projetos

Tem um projeto com IA?

Vamos conversar.

maximofn@gmail.com

Especialista em Machine Learning e Inteligência Artificial. Desenvolvo soluções com IA generativa, agentes inteligentes e modelos personalizados.

Quer assistir alguma palestra?

Últimas palestras -->

Quer melhorar com essas dicas?

Últimos tips -->

Use isso localmente

Os espaços do Hugging Face nos permitem executar modelos com demos muito simples, mas e se a demo quebrar? Ou se o usuário a deletar? Por isso, criei contêineres docker com alguns espaços interessantes, para poder usá-los localmente, aconteça o que acontecer. Na verdade, se você clicar em qualquer botão de visualização de projeto, ele pode levá-lo a um espaço que não funciona.

Flow edit

Flow edit Flow edit

Edite imagens com este modelo de Flow. Baseado em SD3 ou FLUX, você pode editar qualquer imagem e gerar novas

FLUX.1-RealismLora

FLUX.1-RealismLora FLUX.1-RealismLora
Ver todos os contêineres -->
>_ Disponível para projetos

Tem um projeto com IA?

Vamos conversar.

maximofn@gmail.com

Especialista em Machine Learning e Inteligência Artificial. Desenvolvo soluções com IA generativa, agentes inteligentes e modelos personalizados.

Você quer treinar seu modelo com esses datasets?

short-jokes-dataset

HuggingFace

Dataset com piadas em inglês

Uso: Fine-tuning de modelos de geração de texto humorístico

231K linhas 2 colunas 45 MB
Ver no HuggingFace →

opus100

HuggingFace

Dataset com traduções de inglês para espanhol

Uso: Treinamento de modelos de tradução inglês-espanhol

1M linhas 2 colunas 210 MB
Ver no HuggingFace →

netflix_titles

HuggingFace

Dataset com filmes e séries da Netflix

Uso: Análise de catálogo Netflix e sistemas de recomendação

8.8K linhas 12 colunas 3.5 MB
Ver no HuggingFace →
Ver mais datasets -->