Expresiones regulares en Go con ejemplos
Las expresiones regulares (regex) son una herramienta poderosa para buscar, extraer y reemplazar texto según un patrón. En el lenguaje Go (Golang), el trabajo con expresiones regulares se implementa a través del paquete estándar regexp. En este artículo, analizaremos en detalle cómo usar expresiones regulares en Go: desde la búsqueda simple hasta reemplazos complejos con grupos de captura.
1. Fundamentos del paquete regexp
El paquete regexp proporciona dos enfoques principales: uso rápido único (funciones a nivel de paquete) y trabajo eficiente con un patrón precompilado (estructura Regexp). Para uso repetido, compile siempre el patrón de antemano.
Compilación de la expresión regular
package main
import (
"fmt"
"regexp"
)
func main() {
// Compilación del patrón (método recomendado con manejo de errores)
pattern, err := regexp.Compile(`\\d+`)
if err != nil {
fmt.Println("Error de compilación:", err)
return
}
// Para casos simples — sin manejo de errores (panic si el patrón no es válido)
patternMust := regexp.MustCompile(`[a-z]+`)
fmt.Println(pattern, patternMust)
}
Compile devuelve un error si el patrón no es válido. MustCompile provoca un panic — úselo solo para patrones estáticos.
2. Operaciones básicas: búsqueda y verificación
Consideremos los métodos principales para verificar coincidencias y buscar subcadenas.
Verificación de coincidencia parcial
pattern := regexp.MustCompile(`go`)
text := "Estoy estudiando Golang"
// MatchString — ¿la cadena contiene una subcadena que coincide con el patrón?
matched := pattern.MatchString(text)
fmt.Println(matched) // true (ya que "go" está contenido en "Golang")
Verificación de coincidencia completa
// Para verificar que toda la cadena coincide con el patrón, use los anclajes ^ y $
fullPattern := regexp.MustCompile(`^[a-zA-Z]+$`)
fmt.Println(fullPattern.MatchString("Hello")) // true
fmt.Println(fullPattern.MatchString("Hello1")) // false
Búsqueda de la primera coincidencia
datePattern := regexp.MustCompile(`\\d{2}\\.\\d{2}\\.\\d{4}`)
text := "Hoy es 15.03.2024, y mañana será 16.03.2024"
// FindString — devuelve la primera coincidencia
firstDate := datePattern.FindString(text)
fmt.Println(firstDate) // "15.03.2024"
Búsqueda de todas las coincidencias
// FindAllString — devuelve un slice de todas las coincidencias
allDates := datePattern.FindAllString(text, -1) // -1 — todas las coincidencias
fmt.Println(allDates) // ["15.03.2024" "16.03.2024"]
// Limitación de cantidad: FindAllString(text, 1) — solo la primera
3. Grupos de captura y sustituciones
Los grupos de captura permiten extraer partes de la coincidencia. En Go, los grupos se indican con paréntesis ().
Extracción de datos por grupos
// Patrón para extraer nombre y edad: "Nombre: [nombre], Edad: [número]"
personPattern := regexp.MustCompile(`Nombre: (\\w+), Edad: (\\d+)`)
text := "Nombre: Alexei, Edad: 30"
// FindStringSubmatch — devuelve un slice: [coincidencia_completa, grupo1, grupo2, ...]
matches := personPattern.FindStringSubmatch(text)
if len(matches) > 0 {
fmt.Println("Coincidencia completa:", matches[0]) // "Nombre: Alexei, Edad: 30"
fmt.Println("Nombre:", matches[1]) // "Alexei"
fmt.Println("Edad:", matches[2]) // "30"
}
Grupos con nombre (Go 1.21+)
// Desde Go 1.21 se pueden usar grupos con nombre: (?P<nombre>patrón)
pattern := regexp.MustCompile(`(?P<name>\\w+)@(?P<domain>\\w+\\.\\w+)`)
text := "test@example.com"
// SubexpNames — obtenemos los nombres de los grupos
groupNames := pattern.SubexpNames()
matches := pattern.FindStringSubmatch(text)
// Creamos un mapa: nombre_grupo -> valor
```