Golang:从文本文件中读取无效的 JSON

我有一个包含以下示例数据的 txt 文件:


host{

      Entry {

          id: "foo"

      }

       Entry {

          id: "bar"

      }

    }


port{

      Entry {

          id: "lorem"

      }

       Entry {

          id: "ipsum"

      }

    }

它有 +300 的条目值。我想读取文件并提取属于端口部分的id值。它不是有效的 JSON,所以我不能使用 json 解码器,还有其他提取值的方法吗?


呼如林
浏览 193回答 2
2回答

喵喔喔

如果结构始终相同并且您想要的只是 id 值,您可以执行以下操作(在 Playground 上):package mainimport (    "fmt"    "strings")func main() {    // This will work only if ids don't have spaces    fields := strings.Fields(input1)    for i, field := range fields {        if field == "id:" {            fmt.Println("Got an id: ", fields[i+1][1:len(fields[i+1])-1])        }    }    fmt.Println()    // This will extract all strings enclosed in ""    for i1, i2 := 0, 0;; {        i := strings.Index(input2[i1:], "\"") // find the first " starting after the last match        if i > 0 { // if we found one carry on            i1 = i + 1 + i1 // set the start index to the absolute position in the string            i2 = strings.Index(input2[i1:], "\"") // find the second "            fmt.Println(input2[i1 : i1+i2]) // print the string between ""            i1 += i2 + 1 // set the new starting index to after the last match        } else { // otherwise we are done            break        }    }    // Reading the text line by line and only processing port sections    parts := []string{"port{", "  Entry {", "      id: \"foo bar\"", "  }", "   Entry {", "      id: \"more foo bar\"", "  }", "}"}            isPortSection := false    for _, part := range parts {        if string.HasPrefix(part, "port"){            isPortSection = true        }        if string.HasPrefix(part, "host"){            isPortSection = false        }        if isPortSection && strings.HasPrefix(strings.TrimSpace(part),"id:") {            line := strings.TrimSpace(part)            fmt.Println(line[5:len(line)-1])        }    }}var input1 string = `port{  Entry {      id: "foo"  }   Entry {      id: "bar"  }}`var input2 string = `port{  Entry {      id: "foo bar"  }   Entry {      id: "more foo bar"  }}`印刷:Got an id:  fooGot an id:  barfoo barmore foo bar您可以将它们粘贴到切片或地图中,或者做任何您想做/需要做的事情,而不是在循环中打印它们。当然,而不是使用您在文件行中读取的字符串文字。

HUWWW

我相信text/scanner在这里可能非常有用。它不是即插即用,但允许您标记输入并很好地解析您的字符串(空格、转义值等)。概念的快速证明,带有简单状态机的扫描仪,用于捕获分段中的所有id: {str}模式Entry:var s scanner.Scanners.Init(strings.NewReader(src))// Keep state of parsing processconst (    StateNone = iota    StateID    StateIDColon)state := StateNonelastToken := ""        // last token textsections := []string{} // section stacktok := s.Scan()for tok != scanner.EOF {    txt := s.TokenText()    switch txt {    case "id":        if state == StateNone {            state = StateID        } else {            state = StateNone        }    case ":":        if state == StateID {            state = StateIDColon        } else {            state = StateNone        }    case "{":        // Add section        sections = append(sections, lastToken)    case "}":        // Remove section        if len(sections) > 0 {            sections = sections[0 : len(sections)-1]            }    default:        if state == StateIDColon && sections[0] == "port" {            // Our string is here            fmt.Println(txt)        }        state = StateNone    }    lastToken = txt    tok = s.Scan()}你可以在这里玩。如果您需要验证输入结构等,这肯定需要更多的工作,但对我来说似乎是一个很好的起点。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go