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

时间:2019-04-20 15:42:00

标签: regex go

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

"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

3 个答案:

答案 0 :(得分:3)

另一种方法-您可以使用带有自定义split function的扫描器,以按对定界符<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> <button type="button" class="btn btn-lg btn-danger" data-toggle="popover" data-content="You've clicked on this button three times">Click 3 times</button> <script src="https://code.jquery.com/jquery-3.4.0.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>进行拆分,并扫描每个单独的密钥对。然后用“-”分隔键值对文本,以分隔键和值。

;

并如下定义customSplitFunc

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
}

答案 1 :(得分:1)

^"(.+?)(?<!\\)"\s*=\s*"([\s\S]*?)(?<!\\)";将键和值分为两组,假设它们都以"key" = "value";的形式出现。键和值可以使用转义引号。空键不匹配。

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

我在(?<!\\)后使用否定的外观,以确保引号前面没有反斜杠。

答案 2 :(得分: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