Tracks
/
Julia
Julia
/
Temario
/
Expresiones regulares
Ex

Expresiones regulares en Julia

4 ejercicios

Acerca de Expresiones regulares

Las expresiones regulares son una forma muy versátil de hacer coincidencia de patrones en strings, usando un lenguaje específico de dominio (DSL) diseñado para ese fin.

Como varios otros lenguajes de programación, Julia no intenta implementar su propia biblioteca de expresiones regulares. En su lugar, envuelve la popular biblioteca PCRE2, lo que da una sintaxis de expresiones regulares idéntica a la de (por ejemplo) Gleam, y muy similar a la de JavaScript.

Note

Este temario de Julia da por sentado que ya conoces la sintaxis básica de las expresiones regulares. Nos concentraremos únicamente en las características específicas de Julia.

A continuación se listan algunos recursos para repasar tus conocimientos sobre expresiones regulares.

La interfaz de Julia con las expresiones regulares se describe en el manual.

Una expresión regular en Julia es simplemente un string precedido por r antes de la comilla de apertura ". Toda la funcionalidad básica forma parte de la biblioteca estándar.

De hecho, muchas de las funciones que ya vimos en el concepto Strings están diseñadas para hacer búsquedas con expresiones regulares de forma estándar, como occursin().

julia> re = r"test$"
r"test$"

julia> typeof(re)
Regex

# Does a string end with "test"?
julia> occursin(re, "this is a test")
true

julia> occursin(re, "these are tests")
false

Los caracteres modificadores pueden ir después de las comillas de cierre, como i para una coincidencia que no distingue entre mayúsculas y minúsculas.

julia> occursin(r"test", "Testing")
false

julia> occursin(r"test"i, "Testing")
true

Capturas

Con frecuencia queremos saber qué coincide. Esto se logra incluyendo grupos de captura entre paréntesis dentro de la expresión regular y después usando la función match().

julia> m = match(r"(\d+g) .* (\d+ml)", "dissolve 25g sugar in 200ml water")
RegexMatch("25g sugar in 200ml", 1="25g", 2="200ml")

julia> m.captures
2-element Vector{Union{Nothing, SubString{String}}}:
 "25g"
 "200ml"

# how many matches?
julia> length(m.captures)
2

# what matched?
julia> m[1], m[2]
("25g", "200ml")

# Starting positions of the matches (character index)
julia> m.offsets
2-element Vector{Int64}:
 10
 23

Por supuesto, las coincidencias pueden fallar. En ese caso, el resultado será el valor especial Nothing en lugar de un RegexMatch, así que prepárate para comprobarlo.

# failed match
m = match(r"(not here)", "dissolve 25g sugar in 200ml water")

julia> typeof(m)
Nothing

julia> isnothing(m)
true

Aunque match empieza por defecto al inicio del string, también podemos especificar un desplazamiento n para ignorar los primeros n caracteres.

# capture first match
julia> m = match(r"(\wat)", "cat, sat, mat")
RegexMatch("cat", 1="cat")

# ignore first 5 characters, then match
julia> m = match(r"(\wat)", "cat, sat, mat", 5)
RegexMatch("sat", 1="sat")

En Julia, match() solo encuentra la primera coincidencia dentro del string de destino: no hay un modificador global como en otros lenguajes.

En su lugar, tenemos eachmatch(), que devuelve un iterador de coincidencias. Se evalúa de forma perezosa, así que quizá tengas que convertirlo al formato que necesites.

julia> matches = eachmatch(r"(\wat)", "cat, sat, mat")
Base.RegexMatchIterator{String}(r"(\wat)", "cat, sat, mat", false)

# convert to vector
julia> collect(matches)
3-element Vector{RegexMatch}:
 RegexMatch("cat", 1="cat")
 RegexMatch("sat", 1="sat")
 RegexMatch("mat", 1="mat")

# convert with comprehension
julia> [m.match for m in matches]
3-element Vector{SubString{String}}:
 "cat"
 "sat"
 "mat"

# broadcast an anonymous function
julia> (m -> m.match).(matches)
3-element Vector{SubString{String}}:
 "cat"
 "sat"
 "mat"

Las coincidencias superpuestas no se permiten de forma predeterminada. Agrega overlap = true como argumento de palabra clave para cambiar esto.

julia> eachmatch(r"aba", "abababa") |> collect  # matches at positions 1, 5
2-element Vector{RegexMatch}:
 RegexMatch("aba")
 RegexMatch("aba")

julia> eachmatch(r"aba", "abababa"; overlap = true) |> collect  # also matches at position 3
3-element Vector{RegexMatch}:
 RegexMatch("aba")
 RegexMatch("aba")
 RegexMatch("aba")

Reemplazar

Una razón común para usar una expresión regular es reemplazar la coincidencia con un string diferente.

La función replace() ya se comentó en el concepto Strings, usando literales de string para buscar. Esa misma función puede aprovechar todo el poder de las coincidencias con expresiones regulares.

julia> replace("some string", r"[aeiou]" => "*")
"s*m* str*ng"

julia> replace("first second", r"(\w+) (?<agroup>\w+)" => s"\g<agroup> \1")
"second first"

El segundo ejemplo de arriba muestra cómo se pueden usar grupos de captura numerados y con nombre en el reemplazo, dentro de un string s" ".

Consulta el manual para más detalles: ¡este es un tema que constantemente obliga a la mayoría de los programadores a volver a la documentación!

Editar en GitHub El enlace se abre en una ventana o pestaña nueva

Aprende Expresiones regulares

La práctica está bloqueada

Desbloquea 3 ejercicios más para practicar Expresiones regulares