Regexp es una herramienta complicada pero de gran alcance para la comparación de patrones y la manipulación de texto. Aunque su rendimiento es inferior a la coincidencia de texto puro, es más flexible. Base en su sintaxis, casi se puede filtrar cualquier tipo de texto de su contenido de origen. Si usted necesita para recoger datos en el desarrollo web, no es difícil de usar Regexp tener datos significativos.
Go tiene el package regexp
como el apoyo a expresiones regulares, si ya has probado regexp en otros lenguajes de programación, usted debe estar familiarizado con él. Tenga en cuenta que Go implementado estándar RE2 standard except \C
, mas detalles: http://code.google.com/p/re2/wiki/Syntax.
Actualmente, el package strings
hace muchos de estos trabajos buscando(Contains, Index), reempazando(Replace), analizando(Split, Join), etc. y es más rápido que Regexp, cuando se trata de operaciones sencillas. Si quiere buscar una cadena sin mayúsculas y minúsculas, Regexp debe ser su mejor opción. Así que si el paquete cuerdas pueden lograr su objetivo, sólo lo utilizan, es fácil de usar y leer; si necesita operación más avanzada, utilice Regexp obviamente.
Si te acuerdas de verificación forma que hablamos antes, utilizamos Regexp para verificar si la información de entrada es válida allí ya. Tenga en cuenta que todos los personajes son UTF-8, y vamos a aprender más acerca de Go regexp
!
Package regexp
tiene 3 funciones a la altura, si coincide devuelve true, devuelve false en caso contrario.
func Match(pattern string, b []byte) (matched bool, error error)
func MatchReader(pattern string, r io.RuneReader) (matched bool, error error)
func MatchString(pattern string, s string) (matched bool, error error)
Las 3 funciones comprobar si pattern
coincide con la fuente de entrada, devuelve true si coincide, pero si su Regex tiene error de sintaxis, devolverá error. Las 3 fuentes de entrada de estas funciones son slice of byte
, RuneReader
and string
.
Aquí hay un ejemplo para verificar la dirección IP:
func IsIP(ip string) (b bool) {
if m, _ := regexp.MatchString("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$", ip); !m {
return false
}
return true
}
Como se puede ver, utilizando el patrón en el package regexp
no es tan diferente. Un ejemplo más, para verificar si la entrada del usuario es válido:
func main() {
if len(os.Args) == 1 {
fmt.Println("Usage: regexp [string]")
os.Exit(1)
} else if m, _ := regexp.MatchString("^[0-9]+$", os.Args[1]); m {
fmt.Println("Number")
} else {
fmt.Println("Not number")
}
}
En los ejemplos anteriores, utilizamos Match(Reader|Sting)
para comprobar si el contenido es válido, todos ellos son fáciles de usar.
El modo de ajuste puede verificar el contenido, pero no se puede cortar, filtrar o recopilar datos de contenido. Si quieres hacer eso, usted tiene que utilizar el modo complejo de Regexp.
A veces tenemos que escribir un rastreo, aquí es un ejemplo que demuestra que usted tiene que utilizar Regexp filtrar y cortar datos.
package main
import (
"fmt"
"io/ioutil"
"net/http"
"regexp"
"strings"
)
func main() {
resp, err := http.Get("http://www.baidu.com")
if err != nil {
fmt.Println("http get error.")
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("http read error")
return
}
src := string(body)
// Convert HTML tags to lower case.
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllStringFunc(src, strings.ToLower)
// Remove STYLE.
re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
src = re.ReplaceAllString(src, "")
// Remove SCRIPT.
re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
src = re.ReplaceAllString(src, "")
// Remove all HTML code in angle brackets, and replace with newline.
re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllString(src, "\n")
// Remove continuous newline.
re, _ = regexp.Compile("\\s{2,}")
src = re.ReplaceAllString(src, "\n")
fmt.Println(strings.TrimSpace(src))
}
En este ejemplo, utilizamos los datos como el primer paso para el modo complejo. Verifica si su sintaxis Regex es correcta, entonces devuelve Regexp para analizar el contenido en otras operaciones.
Estas son algunas de las funciones para analizar la sintaxis Regexp:
func Compile(expr string) (*Regexp, error)
func CompilePOSIX(expr string) (*Regexp, error)
func MustCompile(str string) *Regexp
func MustCompilePOSIX(str string) *Regexp
La diferencia entre ComplePOSIX
and Compile
es que el primero tiene que usar la sintaxis POSIX que está más a la izquierda de búsqueda más largo, y el último es sólo más a la izquierda en esta categoría. Por ejemplo, para Regexp [a-z]{2,4}
y el contenido "aa09aaa88aaaa"
, CompilePOSIX
devuelve aaaa
pero Compile
retorna aa
. El prefijo Must
se debe anteponer significa pánico cuando la sintaxis Regexp no es correcto, devuelve error sólo lo contrario.
Después de saber cómo crear un nuevo Regexp, vamos a ver esta estructura ofrece lo que los métodos que nos ayudan a operar contenido:
func (re *Regexp) Find(b []byte) []byte
func (re *Regexp) FindAll(b []byte, n int) [][]byte
func (re *Regexp) FindAllIndex(b []byte, n int) [][]int
func (re *Regexp) FindAllString(s string, n int) []string
func (re *Regexp) FindAllStringIndex(s string, n int) [][]int
func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string
func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int
func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte
func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int
func (re *Regexp) FindIndex(b []byte) (loc []int)
func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int)
func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int
func (re *Regexp) FindString(s string) string
func (re *Regexp) FindStringIndex(s string) (loc []int)
func (re *Regexp) FindStringSubmatch(s string) []string
func (re *Regexp) FindStringSubmatchIndex(s string) []int
func (re *Regexp) FindSubmatch(b []byte) [][]byte
func (re *Regexp) FindSubmatchIndex(b []byte) []int
Estos 18 procedimientos que incluyen misma función para diferentes fuentes de entrada, (byte slice, string and io.RuneReader), podemos simplificarlo al ignorar las fuentes de entrada de la siguiente manera:
func (re *Regexp) Find(b []byte) []byte
func (re *Regexp) FindAll(b []byte, n int) [][]byte
func (re *Regexp) FindAllIndex(b []byte, n int) [][]int
func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte
func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int
func (re *Regexp) FindIndex(b []byte) (loc []int)
func (re *Regexp) FindSubmatch(b []byte) [][]byte
func (re *Regexp) FindSubmatchIndex(b []byte) []int
Code sample:
package main
import (
"fmt"
"regexp"
)
func main() {
a := "I am learning Go language"
re, _ := regexp.Compile("[a-z]{2,4}")
// Find the first match.
one := re.Find([]byte(a))
fmt.Println("Find:", string(one))
// Find all matches and save to a slice, n less than 0 means return all matches, indicates length of slice if it's greater than 0.
all := re.FindAll([]byte(a), -1)
fmt.Println("FindAll", all)
// Find index of first match, start and end position.
index := re.FindIndex([]byte(a))
fmt.Println("FindIndex", index)
// Find index of all matches, the n does same job as above.
allindex := re.FindAllIndex([]byte(a), -1)
fmt.Println("FindAllIndex", allindex)
re2, _ := regexp.Compile("am(.*)lang(.*)")
// Find first submatch and return array, the first element contains all elements, the second element contains the result of first (), the third element contains the result of second ().
// Output:
// the first element: "am learning Go language"
// the second element: " learning Go ", notice spaces will be outputed as well.
// the third element: "uage"
submatch := re2.FindSubmatch([]byte(a))
fmt.Println("FindSubmatch", submatch)
for _, v := range submatch {
fmt.Println(string(v))
}
// Same thing like FindIndex().
submatchindex := re2.FindSubmatchIndex([]byte(a))
fmt.Println(submatchindex)
// FindAllSubmatch, find all submatches.
submatchall := re2.FindAllSubmatch([]byte(a), -1)
fmt.Println(submatchall)
// FindAllSubmatchIndex,find index of all submatches.
submatchallindex := re2.FindAllSubmatchIndex([]byte(a), -1)
fmt.Println(submatchallindex)
}
Como hemos introducido antes, Regexp también tiene 3 métodos para la coincidencia, que hacen exactamente lo mismo que las funciones exportadas, esas funciones exportadas llamar a estos métodos subyacentes:
func (re *Regexp) Match(b []byte) bool
func (re *Regexp) MatchReader(r io.RuneReader) bool
func (re *Regexp) MatchString(s string) bool
A continuación, vamos a ver cómo hacer el desplazamiento a través Regexp:
func (re *Regexp) ReplaceAll(src, repl []byte) []byte
func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte
func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte
func (re *Regexp) ReplaceAllLiteralString(src, repl string) string
func (re *Regexp) ReplaceAllString(src, repl string) string
func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string
Estos se utilizan en el ejemplo de rastreo, por lo que no explican más que aquí.
Vamos a echar un vistazo a la explicación deExpand
:
func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte
func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte
Entonces, ¿cómo utilizar Expand
?
func main() {
src := []byte(`
call hello alice
hello bob
call hello eve
`)
pat := regexp.MustCompile(`(?m)(call)\s+(?P<cmd>\w+)\s+(?P<arg>.+)\s*$`)
res := []byte{}
for _, s := range pat.FindAllSubmatchIndex(src, -1) {
res = pat.Expand(res, []byte("$cmd('$arg')\n"), src, s)
}
fmt.Println(string(res))
}
En este punto, usted aprendió sobre el package regexp
en Go, espero que puedan entender más al estudiar ejemplos de métodos clave, y hacer algo interesante por sí mismo.