Golang正则表达式,用于将键值对解析为字符串映射

时间:2017-05-31 06:27:16

标签: regex dictionary go

我希望使用正则表达式将以下字符串解析为map[string]string

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但是不能提出合适的正则表达式吗?这是正确的方法吗?

3 个答案:

答案 0 :(得分:4)

您可以简单地使用github.com/kr/logfmt package

,而不是自己编写正则表达式
  

Package实现了logfmt键值对的解码。

     

示例logfmt消息:

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

JSON中的示例结果:

{ 
    "foo": "bar", 
    "a": 14, 
    "baz": "hello kitty", 
    "cool%story": "bro", 
    "f": true, 
    "%^asdf": true 
}

答案 1 :(得分:4)

这不是使用正则表达式,而只是使用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)
    }
}

答案 2 :(得分:1)

在正则表达式和FindStringSubmatch和SubexpNames函数中使用命名捕获组。 E.g:

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是包含所有子匹配的列表。第一个子匹配是与正则表达式匹配的整个表达式,后跟每个捕获组的子匹配。

如果您需要更频繁地将代码包装到函数中(例如,如果您需要像pythons 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]
}