将包含字符串键/值的文件转换为Go映射

问题描述 投票:0回答:3

我有一个文件,其中包含由=符号分隔的字符串键/值对。它看起来像这样:

"some.key" = "A cool value.";
"some.other.key" = "A cool value with %@ chars and \n. Another Thing.";
"escaped.key" = "A cool \"value\".";
"multiline.key.value" = "1. First sentence is "cool"\
2. Second sentence\
3. Third sentence\
4. Fourth sentence";

请注意,值可以在其中转义引号,并且它们也可以跨越多行。

我已经尝试过基本的引用匹配,但是它没有处理值中的转义引号等等......这就是我现在正在尝试的内容:

file, err := ioutil.ReadFile("/my/string/file")
if err != nil {
    log.Fatal(err)
}

re := regexp.MustCompile(`".*?"`)
match := re.FindAllString(string(file), -1)
fmt.Println(match)

任何帮助将不胜感激:D

regex go
3个回答
3
投票

一种不同的方法 - 您可以使用具有自定义split function的扫描仪来分割您的对分隔符;并扫描每个单独的密钥对。然后用“ - ”分割键值对文本以分割键和值。

file, err := os.Open("/my/string/file")
if err != nil {
    log.Fatal(err)
}
defer f.Close()

scanner := bufio.NewScanner(f)
scanner.Split(customSplitFunc)
for scanner.Scan() {
    fmt.Println("Key-Value Pair: ", scanner.Text())
    //Split scanner.Text() by "=" to split key and value
}

并定义customSplitFunc,如下所示

func customSplitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }

    if atEOF {
        return len(data), data, nil
    }

    //; followed by newline is the k-v pair delimiter
    if i := strings.Index(string(data), ";\n"); i >= 0 {
        //skip the delimiter in advancing to the next pair
        return i + 2, data[0:i], nil
    }
    return
}

1
投票

^"(.+?)(?<!\\)"\s*=\s*"([\s\S]*?)(?<!\\)";匹配两组中的键和值,假设它们都是"key" = "value";形式。键和值可以有转义报价。空键不匹配。

然后,您可以使用\\\n\n替换为跨越多行的值。

我在(?<!\\)背后使用负面看法,以确保引号前面没有反斜杠。


1
投票

我认为(?m)^"([^"]+)"\s*=\s*"(([^"]|(\\")|(\\\n))+)";$做你想要的。与FindAllStringSubmatch一起使用它将返回所有匹配的对。请注意,如果任何输入的语法无效,则整个内容将不匹配,因此可能不是您想要的。

func main() {
    re := regexp.MustCompile(`(?m)^"([^"]+)"\s*=\s*"(([^"]|(\\")|(\\\n))+)";$`)
    matches := re.FindAllStringSubmatch(`"some.key" = "A cool value.";
"some.other.key" = "A cool value with %@ chars and \n. Another Thing.";
"escaped.key" = "A cool \"value\".";
"multiline.key.value" = "1. First sentence is \"cool\"\
2. Second sentence\
3. Third sentence\
4. Fourth sentence";
`, -1)
    for _, m := range matches {
        fmt.Printf("%q %q\n", m[1], m[2])
    }
}

(我在输入的第四行添加了缺少的反斜杠。)

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

© www.soinside.com 2019 - 2024. All rights reserved.