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 buscar coincidencias de patrones en strings, usando un lenguaje de dominio específico (DSL) diseñado para ello.

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 proporciona 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 estás familiarizado con la sintaxis básica de las expresiones regulares. Nos centraremos únicamente en las funcionalidades específicas de Julia.

A continuación se enumeran algunos recursos para refrescar 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 " de apertura. Toda la funcionalidad básica forma parte de la biblioteca estándar.

De hecho, muchas de las funciones que ya se han tratado en el concepto Strings están diseñadas para búsquedas con expresiones regulares de serie, 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 la comilla 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

A menudo queremos saber qué coincide. Esto se consigue 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 principio 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 existe un modificador global como en otros lenguajes.

En su lugar, tenemos eachmatch(), que devuelve un iterador de coincidencias. Se evalúa de forma perezosa, por lo que puede que necesites convertirlo al formato que quieras.

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 solapadas no se permiten de forma predeterminada. Añade overlap = true como argumento de palabra clave para cambiar este comportamiento.

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 habitual para usar una expresión regular es reemplazar la coincidencia por un string diferente.

La función replace() se trató en el concepto Strings, usando literales de string para buscar. La misma función puede aprovechar toda la potencia 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 tanto grupos de captura numerados como con nombre en el reemplazo, dentro de un string s" ".

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

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

Aprende Expresiones regulares

La práctica está bloqueada

Desbloquea 3 ejercicios más para practicar Expresiones regulares