2015-05-27 7 views
18

Ich portiere eine Bibliothek von Ruby nach Go und habe gerade entdeckt, dass reguläre Ausdrücke in Ruby nicht mit Go (google RE2) kompatibel sind. Es ist mir aufgefallen, dass Ruby & Java (plus andere Sprachen verwenden reguläre Ausdrücke PCRE (Perl kompatibel, die das Aufnehmen von Gruppen unterstützt)), so muss ich meine Ausdrücke neu schreiben, so dass sie ok in Go kompilieren.Wie erhalten Sie Capturing Group Funktionalität in Golang regulären Ausdrücken?

Zum Beispiel, ich habe die folgende Regex:

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

Dieser Eingang akzeptieren soll wie:

2001-01-20 

die diese Gruppen erlauben dem Jahr, Monat und Tag in Variablen erfaßt werden. Um den Wert jeder Gruppe zu ermitteln, ist es sehr einfach. Sie indizieren einfach die zurückgegebenen übereinstimmenden Daten mit dem Gruppennamen und Sie erhalten den Wert zurück. So zum Beispiel das Jahr zu bekommen, so etwas wie dieser Pseudo-Code:

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

Dies ist ein Muster, das ich viel in meinem Ausdrücke verwenden, so dass ich habe viel Umschreiben zu tun.

Also, gibt es eine Möglichkeit, diese Art von Funktionalität in Go Regexp zu bekommen; Wie soll ich diese Ausdrücke umschreiben?

Antwort

29

Wie soll ich diese Ausdrücke umschreiben?

einige Ps hinzufügen, wie here definiert:

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

Querverweis capture Gruppennamen mit re.SubexpNames().

Und verwenden as follows:

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()) 
} 
+0

Ok groß, das aussieht Aber wie würde ich Zugang zu den einzelnen Werten, Jahr, Monat und Tag bekommen? – Zephilim

+0

Vergiss den letzten Kommentar, ich habe diese Antwort gefunden. Es ist alles in der? P, wie Sie sagen :) – Zephilim

+0

Ich bin immer noch verwirrt davon; Ich bin mir nicht sicher, ob sie nach Jahr, Monat usw. adressierbar sind.Ich bekomme ein Array mit vier Werten zurück und kann darin indizieren, aber das war's. –

1

Wenn Sie auf einem Replace-Funktion basiert müssen während Gruppen erfassen können Sie verwenden:

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:] 
} 

Beispiel:

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

7

Ich hatte eine Funktion für die Handhabung von URL-Ausdrücken erstellt, die aber auch Ihren Anforderungen entspricht. Sie können this Schnipsel überprüfen, aber es funktioniert einfach so:

/** 
* 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 
} 

Sie diese Funktion wie verwenden können:

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

und der Ausgang wird sein: ermutigende

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