2013-12-23 50 views
23

我來自python,所以我可能只是不看這個正確的方式。我想創建一個相當複雜的正則表達式,並能夠通過名稱訪問字段匹配。我似乎無法找到一個好例子。最近我設法得到的是這樣的:使用來自Go正則表達式的命名匹配

package main 

import (
    "fmt" 
    "regexp" 
) 

var myExp = regexp.MustCompile(`(?P<first>\d+)\.(\d+).(?P<second>\d+)`) 

func main() { 
    fmt.Printf("%+v", myExp.FindStringSubmatch("1234.5678.9")) 

    match := myExp.FindStringSubmatch("1234.5678.9") 
    for i, name := range myExp.SubexpNames() { 
     fmt.Printf("'%s'\t %d -> %s\n", name, i, match[i]) 
    } 
    //fmt.Printf("by name: %s %s\n", match["first"], match["second"]) 
} 

註釋掉的行是我如何訪問python中的命名字段。什麼是去做這件事的等效方式?或者,如果我需要將匹配轉換爲地圖,那麼去製作然後訪問地圖最常用的方法是什麼?

+0

由於我無法在第一個建議的答案下面添加註釋,所以這看起來像是製作地圖的很多代碼。我建議你編輯答案以顯示訪問地圖中的值。例如 \t結果:= myExp.FindStringSubmatchMap(「1234.5678.9」) \t fmt.Printf(「%s \ n」,result [「second」]) –

+0

沒有名爲'FindStringSubmatchMap'的方法。 – chmike

回答

32

您可以利用map引用您的命名捕捉組如下:

package main 

import (
    "fmt" 
    "regexp" 
) 

var myExp = regexp.MustCompile(`(?P<first>\d+)\.(\d+).(?P<second>\d+)`) 

func main() { 
    match := myExp.FindStringSubmatch("1234.5678.9") 
    result := make(map[string]string) 
    for i, name := range myExp.SubexpNames() { 
     if i != 0 && name != "" { 
      result[name] = match[i] 
     } 
    } 
    fmt.Printf("by name: %s %s\n", result["first"], result["second"]) 
} 

GoPlay

+0

http://play.golang.org/p/n3NRgA_Bgs >> panic:運行時錯誤:索引超出範圍 –

+0

您正在使用無效輸入。 – hwnd

+0

對!我只是想做這樣的事:) >> https://github.com/qeremy/couch-go/blob/master/src/couch/util/util.go#L105 –

2

我沒有信譽評所以請原諒我,如果這不應該是一個'answer',但是我發現上面的答案很有幫助,所以我將它包裝到一個函數中:

func reSubMatchMap(r *regexp.Regexp, str string) (map[string]string) { 
    match := r.FindStringSubmatch(str) 
    subMatchMap := make(map[string]string) 
    for i, name := range r.SubexpNames() { 
     if i != 0 { 
      subMatchMap[name] = match[i] 
     } 
    } 
return subMatchMap 
} 

Playground上的示例使用示例: https://play.golang.org/p/zpLJe0iFwJ

希望這對其他人有用。喜歡Go的指定捕捉組的易用性。