¿Cómo extraer datos mediante expresiones regulares?
Ahora que hemos explorado las expresiones regulares, las cadenas de caracteres (strings) y bytes, podemos echar mano de las expresiones regulares para poder manipular los datos.
Supongamos que tenemos archivo lista.html como el siguiente.
<ul>
<li><span class="nombre">Luis</span><span class="apellido">Perez</span></li>
<li><span class="nombre">Adrian</span><span class="apellido">Romo</span></li>
<li>
<span class="nombre">Daniel</span><span class="apellido">Quiroz</span>
</li>
</ul>
Utilizando expresiones regulares podemos procesar esta cadena de caracteres y obtener la lista de los apellidos.
La solución para este problema es definir una expresión regular que:
- Obtener cada una de las lineas.
- Cada línea esta compuesta de 3 bloques:
- La apertura de la etiqueta
span class="name"
, el valor nombre y el cierre de la etiqueta. - Solo requerimos el valor del nombre.
La propuesta es la siguiente:
[apertura][valor][cierre]
(<span class="nombre">)([^<]+)(</span>)
La expresión regular anterior es una sola, pero he encerrado cada parte de la expresión entre paréntesis, esto permite separarlo en tres partes.
Para realizar esta operación utilizamos la función FindAllSubmatchIndex
. La cual recibe un arreglo de bytes y retorna un arreglo con cada una de las coincidencias de la expresión regular, sin embargo estas coincidencias no son el string sino un arreglo de indices el cual contiene:
- La posición inicial y final de la coincidencia en el arreglo de bytes.
- La posición inicial y final de la primera expresión encerrada entre paréntesis.
- La posición inicial y final de la siguiente expresión encerrada entre paréntesis.
- Así sucesivamente hasta completar la última expresión.
Por ejemplo para la primera coincidencia:
<span class="nombre">Luis</span>
[a,b,c,d,e,f,g,h]
Si del arreglo de bytes imprimiéramos:
[posicion[a]:posicion[b]]
=<span class="nombre">Luis</span>
[posicion[c]:posicion[d]]
=<span class="nombre">
[posicion[e]:posicion[f]]
=Luis
[posicion[g]:posicion[h]]
=</span>
Vamos a ver el ejemplo completo…
package main
import (
"fmt"
"io/ioutil"
"log"
"regexp"
)
func main() {
// en donde vamos a capturar los nombres
var nombres = make([]string, 3)
// cargar contenido del html
datosComoBytes, err := ioutil.ReadFile("lista.html")
if err != nil {
log.Fatal(err)
}
// preparar la expresion regular
expReg := regexp.MustCompile(`(<span class="nombre">)([^<]+)(</span>)`)
// ejecutar la busqueda de los indices
todosLosIndices := expReg.FindAllSubmatchIndex(datosComoBytes, -1)
// recorrer los resultados y capturar el nombre
for _, loc := range todosLosIndices {
nombres = append(nombres, string(datosComoBytes[loc[4]:loc[5]]))
}
// imprimir los nombres
fmt.Println(nombres)
}
Si ejecutamos el programa obtendremos lo siguiente.
[ Luis Adrian Daniel]