import re
Con el método findall()
podemos encontrar todas las coincidencias de un patrón en un string
string = "Hola, soy un string"
print(re.findall("Hola, soy", string))
Pero si queremos encontrar la posición donde se encuentra un patrón, podemos usar el método search()
para buscar un patrón en un string. Este método devuelve un objeto de tipo Match si encuentra una coincidencia, y si no devuelve None.
print(re.search("soy", string))
También podemos usar el método match()
que busca el patrón al principio del string.
print(re.match("Hola", string))
print(re.match("soy", string))
Si queremos obtener la posición de la coincidencia, podemos usar el método span()
que devuelve una tupla con la posición inicial y final de la coincidencia.
print(re.match("Hola", string).span())
Sabiendo la posición de la coincidencia, podemos usar el método group()
para obtener la subcadena que coincide con el patrón.
print(re.match("Hola", string).group())
También podríamos usar el inicio y el final de la coincidencia para hacer un slice del string.
start, end = re.match("Hola", string).span()
print(string[start:end])
Con el método split()
podemos dividir un string en una lista de subcadenas usando un patrón como separador.
split = re.split("soy", string)
print(split)
Se ha dividido la frase en dos strings usando «soy» como separador.
Con el método sub()
podemos reemplazar todas las coincidencias de un patrón por otra subcadena.
sub = re.sub("soy", "eres", string)
print(sub)
Ha reemplazado todas las coincidencias de «soy» por «eres».
Con el caracter .
podemos buscar cualquier caracter, cualquier caracter que haya en nuestro string será encontrado
string = "Hola, soy un string"
print(re.findall(".", string))
Si por ejemplo queremos secuencias de dos caracteres buscaríamos con dos .
s seguidos
string1 = "Hola, soy un string"
string2 = "Hola, soy un string2"
print(re.findall("..", string1))
print(re.findall("..", string2))
Como podemos ver string1
tiene un numero impar de caracteres, por lo que la última g
no la coge, si embargo string2
tiene un número par de caracteres, por lo que coge todos los caracteres
Vamos a ver esto de otra forma, vamos a cambiar cada secuencia de tres caracteres por un símbolo de $
print(string1)
print(re.sub("...", "$ ", string1))
He impreso dos espacios después de cada $
para que se vea el cambio, se puede ver como el último caracter no lo convierte
Si queremos encontrar los dígitos necesitamos usar \d
string = "Hola, soy un string con 123 digitos"
print(re.findall("\d", string))
Al igual que antes, si por ejemplo queremos dos dígitos, ponemos \d
dos veces
print(re.findall("\d\d", string))
Si queremos encontrar letras necesitamos usar \w
. Se entiende por word
todas las letras de la a
a la z
, de la A
a la Z
, los números de 0
al 9
y el _
string = "Hola, soy un_string con, 123 digitos"
print(re.findall("\w", string))
Como vemos coge todo menos los espacios y la coma
Si queremos encontrar espacios necesitamos \s
string = "Hola, soy un_string con, 123 digitos"
print(re.sub("\s", "*", string))
Las expresiones regulares considera los saltos de línea como espacios
string = """Hola, soy un string
con un salto de línea"""
print(re.sub("\s", "*", string))
Si queremos buscar un rango usamos []
, por ejemplo, si queremos los números del 4 al 8 usamos
string = "1234567890"
print(re.findall("[4-8]", string))
Podemos ampliar el rango de búsqueda
string = "1234567890"
print(re.findall("[2-57-9]", string))
Si además queremos encontrar un caracter en concreto ponemos el carcacter seguido de \
string = "1234567890."
print(re.findall("[2-57-9\.]", string))
Como hemos visto, si queremos encontrar rangos usamos []
, pero ¿qué pasa si queremos encontrar solo el [
o el ]
? Para ello tenemos que usar \[
y \]
string = "[1234567890]"
print(re.findall("\[", string))
print(re.findall("\]", string))
Con el delimitador *
se indica que quieres que te busque ninguno o todos, no uno a uno como antes
string = "Hola, soy un string con 12 123 digitos"
print(re.findall("\d", string))
print(re.findall("\d*", string))
Como se puede ver, al poner el *
ha encontrado todas las posiciones en las que hay cero caracteres o todos los caracteres
Con el delimitador +
se indica que quieres que te busque uno o más
string = "Hola, soy un string con 1 12 123 digitos"
print(re.findall("\d+", string))
Con el delimitador ?
se indica que quieres que te busque cero o uno
string = "Hola, soy un string con 1 12 123 digitos"
print(re.sub("\d?", "-", string))
Cuando queremos encontrar algo que aparezca x veces usamos los contadores mediante las llaves {}
. Por ejemplo, si queremos encontrar una secuencia en la que al menos haya dos dígitos
string = "Hola, soy un string con 1 12 123 1234 1234digitos"
print(re.findall("\d{2}", string))
Como se puede ver ha encontrado las secuencias 12
y 34
Los contadores aceptan una cota superior e inferior {inf, sup}
string = "Hola, soy un string con 1 12 123 1234 1234digitos"
print(re.findall("\d{2,5}", string))
Si no se define la cota superior, significa que se quiere como mínimo la cantidad de elementos que se ha indicado, pero sin límite superior
string = "Hola, soy un string con 1 12 123 1234 12345464168415641646451563416 digitos"
print(re.findall("\d{2,}", string))
Si queremos usar la notación de cota superior e inferior, pero queremos un número fijo, se tiene que poner dicho número en las dos cotas
string = "Hola, soy un string con 1 12 123 1234 12345464168415641646451563416 digitos"
print(re.findall("\d{2,3}", string))
Se pueden crear clases mediante corchetes []
. En realidad vimos que este servía para los rangos, pero, una vez que se define lo que se quiere que haya dentro, se puede considerar como una clase y operar con el
Por ejemplo, supongamos que tenemos un número de teléfono, que puede darse de las siguientes maneras
- 666-66-66-66
- 666-666-666
- 666 666 666
- 666 66 66 66
- 666666666
Hay muchas maneras de dar un número, así que vamos a ver cómo crear una clase para definir el delimitador
Primero vamos a decir que busque todas las secuencias de números en las que haya como mínimo dos números
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("\d{2,}", string1))
print(f"string2: {string2} -->", re.findall("\d{2,}", string2))
print(f"string3: {string3} -->", re.findall("\d{2,}", string3))
print(f"string4: {string4} -->", re.findall("\d{2,}", string4))
print(f"string5: {string5} -->", re.findall("\d{2,}", string5))
Ahora definimos que encuentre el separador como un -
o un espacio
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("[-\s]", string1))
print(f"string2: {string2} -->", re.findall("[-\s]", string2))
print(f"string3: {string3} -->", re.findall("[-\s]", string3))
print(f"string4: {string4} -->", re.findall("[-\s]", string4))
print(f"string5: {string5} -->", re.findall("[-\s]", string5))
Como se ve en el último string no ha encontrado, por lo que añadimos un ?
para que encuentre cuando haya cero o uno
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("[-\s]?", string1))
print(f"string2: {string2} -->", re.findall("[-\s]?", string2))
print(f"string3: {string3} -->", re.findall("[-\s]?", string3))
print(f"string4: {string4} -->", re.findall("[-\s]?", string4))
print(f"string5: {string5} -->", re.findall("[-\s]?", string5))
Ahora buscamos que esté todo junto
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?", string1))
print(f"string2: {string2} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?", string2))
print(f"string3: {string3} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?", string3))
print(f"string4: {string4} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?", string4))
print(f"string5: {string5} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?", string5))
Como vemos en el string2
y string4
, no encuentra nada. Hemos puesto el filtro \d{2,}[\-\s]?
4 veces, es decir queremos una secuencia de al menos dos números, seguido de cero o un separador de tipo guion o espacio que se repita 4 veces. Pero en la última secuencia no hace falta el [\-\s]?
, ya que nunca va a terminar un número con un espacio o un guión
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}", string1))
print(f"string2: {string2} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}", string2))
print(f"string3: {string3} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}", string3))
print(f"string4: {string4} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}", string4))
print(f"string5: {string5} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}", string5))
Sigue sin encontrar para string2
y string4
. Esto es porque lo último que hay en el filtro es un d{2,}
, es decir, después del tercer separador estamos esperando al menos 2 números, pero eso en string2
y string4
no pasa, así que ponemos lo siguiente
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d*", string1))
print(f"string2: {string2} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d*", string2))
print(f"string3: {string3} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d*", string3))
print(f"string4: {string4} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d*", string4))
print(f"string5: {string5} -->", re.findall("\d{2,}[-\s]?\d{2,}[-\s]?\d{2,}[-\s]?\d*", string5))
El ejemplo anterior lo podemos filtrar mediante \d+?[- ]
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("\d+?[- ]", string1))
print(f"string2: {string2} -->", re.findall("\d+?[- ]", string2))
print(f"string3: {string3} -->", re.findall("\d+?[- ]", string3))
print(f"string4: {string4} -->", re.findall("\d+?[- ]", string4))
print(f"string5: {string5} -->", re.findall("\d+?[- ]", string5))
Si no estuviese el delimitador ?
tendríamos \d+[- ]
, lo que quiere decir una secuencia de uno o más números seguidos de un espacio o un guión. Pero lo que hace el delimitador ?
es hacer esta búsqueda más rápido
Antes hemos visto que con \d
encotrábamos dígitos, pues con \D
encontramos todo lo que no sean dígitos
string1 = "E3s4t6e e1s2t3r5i6n7g8 t9i0e4n2e1 d4i5g7i9t0o5s2"
print(re.findall("\D", string1))
Lo mismo ocurre con las letras, si escribimos \W
encontrará todo lo que no sean letras
string1 = "Letras ab27_ no letras ,.:;´ç"
print(re.findall("\W", string1))
Si ponemos \S
encontraremos todo lo que no sean espacios
print(re.findall("\S", string1))
Pero en caso que tengamos una clase o quialquier otra cosa, podemos negar mediante ^
string1 = "1234567890"
print(re.findall("[^5-9]", string1))
Volviendo al ejemplo de los números de teléfono de antes, podemos filtrarlos mediante los siguiente
string1 = "666-66-66-66"
string2 = "666-666-666"
string3 = "666 66 66 66"
string4 = "666 666 666"
string5 = "666666666"
print(f"string1: {string1} -->", re.findall("\d{2,}\D?\d{2,}\D?\d{2,}\D?\d*", string1))
print(f"string2: {string2} -->", re.findall("\d{2,}\D?\d{2,}\D?\d{2,}\D?\d*", string2))
print(f"string3: {string3} -->", re.findall("\d{2,}\D?\d{2,}\D?\d{2,}\D?\d*", string3))
print(f"string4: {string4} -->", re.findall("\d{2,}\D?\d{2,}\D?\d{2,}\D?\d*", string4))
print(f"string5: {string5} -->", re.findall("\d{2,}\D?\d{2,}\D?\d{2,}\D?\d*", string5))
string5 = "666 666 666"
Lo que estamos haciendo es pedir secuencias de al menos dos dígitos seguido de uno o ningún no dígito
Con ^
podemos buscar el inicio de línea, por ejemplo, si queremos encontrar un dígito que solo esté al inicio de una línea
string1 = "linea 1"
string2 = "2ª linea"
print(re.findall("^\d", string1))
print(re.findall("^\d", string2))
Como se puede ver solo hay un dígito al inicio de linea en string2
Al igual, el final de línea se puede encontrar con $
. Si queremos encontrar un dígito solo al final de una línea
string1 = "linea 1"
string2 = "2ª linea"
print(re.findall("\d$", string1))
print(re.findall("\d$", string2))
Esto solo ocurre en el string1
Si en el siguiente log queremos encontrar solo los WARN
s
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
Dentro de un número podemos encontrarnos letras como la e
de extensión, #
también para la extensión, o la p
para que si llama un ordenador haga una pausa. También podemos encontrar el +
para indicar un prefijo de pais y separadores como espacios, -
, .
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\n]?\d{2,3}[^\da-zA-Z\n]?\d{2,3}[#pe]?\d*", tel)
result
Pasamos a explicarlo
\+?
: Que empiece con el caracter+
y que haya cero o uno\d{2,3}
: Que siga con entre 2 y 3 dígitos[^\da-zA-Z\n]?
: A continuación puede haber cero o un caracter que no sea ni un dígito, ni una letra de laa
laz
, ni una letra de laA
a laZ
, ni un salto de línea\d{2,3}
: Que siga con entre 2 y 3 dígitos[^\da-zA-Z\n]?
: A continuación puede haber cero o un caracter que no sea ni un dígito, ni una letra de laa
laz
, ni una letra de laA
a laZ
, ni un salto de línea\d{2,3}
: Que siga con entre 2 y 3 dígitos[#pe]?
: A continuación puede haber cero o un caracter tanto#
, comop
, comoe
\d
: Por último que haya cero o todos los números
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&limit=10&api_key=DG3hItPp5HIRNC0nit3AOR7eQZAe
http://localhost:3000/something?color1=red&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&name=Billy
http://localhost:3000/getUsers?userId=12354411
http://localhost:3000/search?city=Barcelona
www.sitiodeejemplo.net/pagina.php?nombredevalor1=valor1&nombredevalor2=valor2"""
result = re.findall("https?:\/\/[\w\-\.]+\.\w{2,6}\/?\S*", urls)
result
Pasamos a explicarlo
http
: Queremos que empiece porhttp
s?
: A continuación puede haber o no unas
:\/\/
: Seguido de://
[\w\-\.]+
: Seguido de uno o más letras, giones o puntos\.
: A continuación un punto\w{2,6}
: Entre 2 y 6 letras para el tld\/?
: Seguido de cero o un/
\S
: Ninguno o todo lo que no sea un espacio
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
Pasamos a explicarlo
[\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
Hay dos posibles manera de dar localizaciones, por lo que analizamos las dos
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
Pasamos a explicarlo
\-?
: Queremos que empiece con cero o un signo menos\d{1,3}
: Seguido de entre uno y tres números\.
: A continuación un punto\d{1,6}
: Después entre uno y seis números,
: A continuación una,
\s?
: Después cero o un espacio\-?
: Cero o un signo menos\d{1,3}
: A continuación entre uno y tres números\.
: A continuación un punto\d{1,6}
: Seguido de entre uno y seis números,
: Luego una coma
.
: Por último ninguno o todo tipo de caracteres
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}\s\d{1,2}'\s\d{1,2}\.\d{2,2}\"[WE],\s?\-?\d{1,3}\s\d{1,2}'\s\d{1,2}\.\d{2,2}\"[SN]", loc)
result
print(result[0])
print(result[1])
Pasamos a explicarlo
\-?
: Queremos que empiece con cero o un signo menos\d{1,3}
: Seguido de entre uno y tres números\s
: Después un espacio\d{1,2}
: Segiodo de entre uno y dos números'
: A continuación un'
\s
: Seguido de un espacio\d{1,2}
: A continuación entre uno y dos números\.
: Después un punto\d{2,2}
: Seguido de dos números\"
: Después un"
[WE]
: A continuación la letraW
o la letraE
,
: Después una coma\s?
: Seguido de cero o un espacio\-?
: Después cero o un signo menos\d{1,3}
: A continuación entre uno y tres números\s
: Seguido de un espacio\d{1,2}
: A continuación entre uno y dos números'
: Después un'
\s
: Después un espacio\d{1,2}
: A continuación entre uno y dos númeors\.
: Seguido de un punto\d{2,2}
: Después dos números\"
: Segido de"
[SN]
: Y por último la letraS
o la letraN
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
Pasamos a explicarlo
[A-ZÁÉÍÓÚ]
: Queremos que empiece con una letra mayúscula, incluidas con acentos[a-záéíóú]+
: Seguido de una o mas letras minúsculas, incluidas con espacios\s
: Segido de un espacio[A-ZÁÉÍÓÚ]
: A continuación una letra mayúscula, incluidas con acentos[a-záéíóú]+
: Seguido de una o mas letras minúsculas, incluidas con espacios\s
: Segido de un espacio[A-ZÁÉÍÓÚ]
: A continuación una letra mayúscula, incluidas con acentos[a-záéíóú]+
: Seguido de una o mas letras minúsculas, incluidas con espacios
Vamos a descargarnos un archivo con un montón de películas históricas
# 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")
Vamos a imprimir las primeras 10 lineas para analizarlo
file = open("movies.dat", "r")
for i, line in enumerate(file):
print(line, end="")
if i == 10:
break
file.close()
Como se puede ver, tenemos un ID, seguido de ::
, a continuación el nombre de la película, entre paréntesis el año, sguido de ::
y después géneros separados por |
Podemos hacer una limpieza del archivo muy fácil mediante las expresiones regulares, las funciones compile
y match
y el uso de agrupaciones con paréntesis. Al hacer agurpaciones, seleccionamos qué zonas del texto queremos guardar para luego trabajar con ellas como queramos, vamos e verlo con un ejemplo
pattern = re.compile(r"^\d+::([\w\s:,\(\)\.\-'&¡!/¿?ÁÉÍÓÚáéíóú\+*\$#°\'\"\[\]@·]+)\s\((\d{4,4})\)::(.*)$")
file = open("movies.dat", "r")
file_filtered = open("movies.csv", "w")
file_filtered.write("title,year,genders\n")
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)}\n")
else:
print(line, end="")
file.close()
file_filtered.close()
Vamos a ver qué hemos hecho, primero hemos definido un patrón con lo siguiente:
^
: Queremos que empiece con el inicio de línea\d+
: A continuación uno o más números::
: Seguido de::
([\w\s:,\(\)\.\-'&¡!/¿?ÁÉÍÓÚáéíóú\+
\$#°\'\"\[\]@·]+): Esta es la primera agrupación, buscamos cualquier palabra, espacio o caracter de entre los corchetes que aparezca una o más veces
\s
: A continuación un espacio\(
: La apretura de un paréntesis(\d{4,4})
: Aquí esta la segunda agrupación, buscamos cuatro números\)
: Después el cierre de un paréntesis::
: A continuación::
(.
): La tercera agrupación, cualquier caracter que aparezca ninguna o todas las veces
$
: Por último el final de línea
Dentro del for
analizamos línea a línea si se encuentra el patrón que hemos definido, y si se encuentra se escriben los tres patrones en el csv
separados por sep
, que en nuestro caso lo hemos definido como ;;
. Se ha definido ese separador, porque hay títulos de películas que tienen ,
s.
Leemos el csv
con Pandas
import pandas as pd
df = pd.read_csv("movies.csv", sep=";;", engine="python")
df.head()
Aquí tienes un cheatsheet con un montón de patrones