2017-05-31 45 views
1

我期待使用正則表達式來解析以下字符串成map[string]stringGolang正則表達式解析鍵值對成字符串映射

time="2017-05-30T19:02:08-05:00" level=info msg="some log message" app=sample size=10 

我試圖創建一個映射,將有

m["time"] = "2017-05-30T19:02:08-05:00" 
m["level"] = "info" 

我一直在使用regex.FindAllStringIndex嘗試,但不能完全拿出一個合適的正則表達式?這是正確的方法嗎?

+2

使用一個真正的解析器來代替。 – Jan

+0

[RegEx匹配開放標籤,但XHTML自包含標籤除外]的可能重複(https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags) – Jan

回答

2

這是不使用正則表達式,但僅僅是如何實現的例子同樣使用strings.FieldsFunc

https://play.golang.org/p/rr6U8xTJZT

package main 

import (
    "fmt" 
    "strings" 
    "unicode" 
) 

const foo = `time="2017-05-30T19:02:08-05:00" level=info msg="some log message" app=sample size=10` 

func main() { 
    lastQuote := rune(0) 
    f := func(c rune) bool { 
     switch { 
     case c == lastQuote: 
      lastQuote = rune(0) 
      return false 
     case lastQuote != rune(0): 
      return false 
     case unicode.In(c, unicode.Quotation_Mark): 
      lastQuote = c 
      return false 
     default: 
      return unicode.IsSpace(c) 

     } 
    } 

    // splitting string by space but considering quoted section 
    items := strings.FieldsFunc(foo, f) 

    // create and fill the map 
    m := make(map[string]string) 
    for _, item := range items { 
     x := strings.Split(item, "=") 
     m[x[0]] = x[1] 
    } 

    // print the map 
    for k, v := range m { 
     fmt.Printf("%s: %s\n", k, v) 
    } 
} 
+0

這是我最終使用了什麼,但是@kennytm的解決方案同樣很好,只要你有額外的依賴就可以了。 – Xeaz

3

您可以簡單地使用github.com/kr/logfmt package來代替編寫自己的正則表達式。

包實現logfmt鍵 - 值對的解碼。

例logfmt消息:

foo=bar a=14 baz="hello kitty" cool%story=bro f %^asdf 

例結果JSON:

命名爲正則表達式和FindStringSubmatch和SubexpNames功能捕獲組
{ 
    "foo": "bar", 
    "a": 14, 
    "baz": "hello kitty", 
    "cool%story": "bro", 
    "f": true, 
    "%^asdf": true 
} 
0

使用。例如:

s := `time="2017-05-30T19:02:08-05:00" level=info msg="some log message" app=sample size=10` 
re := regexp.MustCompile(`time="(?P<time>.*?)"\slevel=(?P<level>.*?)\s`) 
values := re.FindStringSubmatch(s) 
keys := re.SubexpNames() 

// create map 
d := make(map[string]string) 
for i := 1; i < len(keys); i++ { 
    d[keys[i]] = values[i] 
} 
fmt.Println(d) 
// OUTPUT: map[time:2017-05-30T19:02:08-05:00 level:info] 

values是包含所有子匹配的列表。第一個子匹配是與正則表達式匹配的整個表達式,然後是每個捕獲組的子匹配。

你可以用代碼到一個功能,如果你需要這個更頻繁地(例如,如果你需要像蟒蛇match.groupdict):

package main 

import (
    "fmt" 
    "regexp" 
) 

func groupmap(s string, r *regexp.Regexp) map[string]string { 
    values := r.FindStringSubmatch(s) 
    keys := r.SubexpNames() 

    // create map 
    d := make(map[string]string) 
    for i := 1; i < len(keys); i++ { 
     d[keys[i]] = values[i] 
    } 

    return d 
} 

func main() { 
    s := `time="2017-05-30T19:02:08-05:00" level=info msg="some log message" app=sample size=10` 
    re := regexp.MustCompile(`time="(?P<time>.*?)"\slevel=(?P<level>.*?)\s`) 

    fmt.Println(groupmap(s, re)) 
    // OUTPUT: map[time:2017-05-30T19:02:08-05:00 level:info] 
}