regulares regular probar palabra expresiones expresion exacta espacio ejemplos cualquier crear caracter blanco alfanumerico regex go capture-group

regex - probar - expresiones regulares java



¿Cómo obtener la funcionalidad de grupo de captura en las expresiones regulares de Golang? (4)

Estoy portando una biblioteca de Ruby to Go, y acabo de descubrir que las expresiones regulares en Ruby no son compatibles con Go (google RE2). Me llamó la atención que Ruby y Java (además de otros lenguajes usan expresiones regulares PCRE (perl compatible, que admite grupos de captura)), por lo que necesito volver a escribir mis expresiones para que se compilen en Go

Por ejemplo, tengo el siguiente regex:

`(?<Year>/d{4})-(?<Month>/d{2})-(?<Day>/d{2})`

Esto debería aceptar entradas tales como:

2001-01-20

Los grupos de captura permiten que el año, el mes y el día se capturen en variables. Para obtener el valor de cada grupo, es muy fácil; simplemente indexa los datos coincidentes devueltos con el nombre del grupo y recupera el valor. Así, por ejemplo, para obtener el año, algo así como este pseudo código:

m=expression.Match("2001-01-20") year = m["Year"]

Este es un patrón que uso mucho en mis expresiones, así que tengo que reescribir muchas cosas.

Entonces, ¿hay una manera de obtener este tipo de funcionalidad en Go regexp; ¿Cómo debo reescribir estas expresiones?


¿Cómo debo reescribir estas expresiones?

Agregue algunas Ps, como se define here :

(?P<Year>/d{4})-(?P<Month>/d{2})-(?P<Day>/d{2})

Referencia cruzada de nombres de grupos de captura con re.SubexpNames() .

Y usar de la siguiente manera :

package main import ( "fmt" "regexp" ) func main() { r := regexp.MustCompile(`(?P<Year>/d{4})-(?P<Month>/d{2})-(?P<Day>/d{2})`) fmt.Printf("%#v/n", r.FindStringSubmatch(`2015-05-27`)) fmt.Printf("%#v/n", r.SubexpNames()) }


Había creado una función para manejar expresiones de URL, pero también se adapta a sus necesidades. Puedes revisar this fragmento, pero simplemente funciona así:

/** * Parses url with the given regular expression and returns the * group values defined in the expression. * */ func getParams(regEx, url string) (paramsMap map[string]string) { var compRegEx = regexp.MustCompile(regEx) match := compRegEx.FindStringSubmatch(url) paramsMap = make(map[string]string) for i, name := range compRegEx.SubexpNames() { if i > 0 && i <= len(match) { paramsMap[name] = match[i] } } return }

Puedes usar esta función como:

params := getParams(`(?P<Year>/d{4})-(?P<Month>/d{2})-(?P<Day>/d{2})`, `2015-05-27`) fmt.Println(params)

y la salida será:

map[Year:2015 Month:05 Day:27]


Para mejorar el uso de la RAM y la CPU sin llamar a funciones anónimas dentro del bucle y sin copiar arreglos en la memoria dentro del bucle con la función "agregar", vea el siguiente ejemplo:

Puede almacenar más de un subgrupo con texto multilínea, sin agregar la cadena con ''+'' y sin usar el bucle interno para el bucle (como otros ejemplos publicados aquí).

txt := `2001-01-20 2009-03-22 2018-02-25 2018-06-07` regex := *regexp.MustCompile(`(?s)(/d{4})-(/d{2})-(/d{2})`) res := regex.FindAllStringSubmatch(txt, -1) for i := range res { //like Java: match.group(1), match.gropu(2), etc fmt.Printf("year: %s, month: %s, day: %s/n", res[i][1], res[i][2], res[i][3]) }

Salida:

year: 2001, month: 01, day: 20 year: 2009, month: 03, day: 22 year: 2018, month: 02, day: 25 year: 2018, month: 06, day: 07

Nota: res [i] [0] = ~ match.group (0) Java

Si desea almacenar esta información use un tipo de estructura:

type date struct { y,m,d int } ... func main() { ... dates := make([]date, 0, len(res)) for ... { dates[index] = date{y: res[index][1], m: res[index][2], d: res[index][3]} } }

Es mejor usar grupos anónimos (mejora del rendimiento)

Usar "ReplaceAllGroupFunc" publicado en Github es una mala idea porque:

  1. está usando bucle dentro de bucle
  2. está usando una función anónima llamada dentro del bucle
  3. tiene mucho código
  4. está usando la función "agregar" dentro del bucle y eso es malo. Cada vez que se realiza una llamada a la función "añadir", se está copiando la matriz a la nueva posición de memoria

Si necesita reemplazar en función de una función mientras captura grupos, puede usar esto:

import "regexp" func ReplaceAllGroupFunc(re *regexp.Regexp, str string, repl func([]string) string) string { result := "" lastIndex := 0 for _, v := range re.FindAllSubmatchIndex([]byte(str), -1) { groups := []string{} for i := 0; i < len(v); i += 2 { groups = append(groups, str[v[i]:v[i+1]]) } result += str[lastIndex:v[0]] + repl(groups) lastIndex = v[1] } return result + str[lastIndex:] }

Ejemplo:

str := "abc foo:bar def baz:qux ghi" re := regexp.MustCompile("([a-z]+):([a-z]+)") result := ReplaceAllGroupFunc(re, str, func(groups []string) string { return groups[1] + "." + groups[2] }) fmt.Printf("''%s''/n", result)

https://gist.github.com/elliotchance/d419395aa776d632d897