在Go中解析格式化的字符串

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

问题

我有一些string值,其中每个值都是基于模板格式化的。在我的特定情况下,我正在尝试解析Markdown URL,如下所示:

- [What did I just commit?](#what-did-i-just-commit)
- [I wrote the wrong thing in a commit message](#i-wrote-the-wrong-thing-in-a-commit-message)
- [I committed with the wrong name and email configured](#i-committed-with-the-wrong-name-and-email-configured)
- [I want to remove a file from the previous commit](#i-want-to-remove-a-file-from-the-previous-commit)
- [I want to delete or remove my last commit](#i-want-to-delete-or-remove-my-last-commit)
- [Delete/remove arbitrary commit](#deleteremove-arbitrary-commit)
- [I tried to push my amended commit to a remote, but I got an error message](#i-tried-to-push-my-amended-commit-to-a-remote-but-i-got-an-error-message)
- [I accidentally did a hard reset, and I want my changes back](#i-accidentally-did-a-hard-reset-and-i-want-my-changes-back)

我想做的事?

我正在寻找方法将其解析为类型的值:

type Entity struct {
    Statement string
    URL string
}

我试过了什么?

如您所见,所有项目都遵循以下模式:- [{{ .Statement }}]({{ .URL }})。我尝试使用fmt.Sscanf函数扫描每个字符串:

var statement, url string
fmt.Sscanf(s, "[%s](%s)", &statement, &url)

这导致:

statement = "I"
url = ""

问题在于扫描仪仅存储空格分隔值。我不明白为什么没有根据此规则填充URL字段。

如何获得上面提到的Markdown值?

编辑:正如Marc所建议的那样,我将补充几点澄清点:

  1. 这是基于格式解析字符串的一般目的问题。在我的特定情况下,Markdown解析器可能对我有帮助,但我打算学习如何处理这些可能不存在库的情况。
  2. 我在发布之前已经阅读了官方文档。
string go
2个回答
3
投票

注意:以下解决方案仅适用于“简单”,非转义输入降价链接。如果这符合您的需求,请继续使用。要获得完全降价兼容性,您应该使用正确的降价解析器,例如gopkg.in/russross/blackfriday.v2


您可以使用正则表达式从标记链接中获取链接文本和URL。

因此一般输入文本的形式为:

[some text](somelink)

一个模拟这个的正则表达式:

\[([^\]]+)\]\(([^)]+)\)

哪里:

  • \[是字面上的[
  • ([^\]]+)用于"some text",它是除了关闭方括号之外的所有东西
  • \]是字面上的]
  • \(是字面上的(
  • ([^)]+)"somelink",除了右边括号之外的所有东西
  • \)是字面上的)

例:

r := regexp.MustCompile(`\[([^\]]+)\]\(([^)]+)\)`)

inputs := []string{
    "[Some text](#some/link)",
    "[What did I just commit?](#what-did-i-just-commit)",
    "invalid",
}

for _, input := range inputs {
    fmt.Println("Parsing:", input)
    allSubmatches := r.FindAllStringSubmatch(input, -1)

    if len(allSubmatches) == 0 {
        fmt.Println("   No match!")
    } else {
        parts := allSubmatches[0]
        fmt.Println("   Text:", parts[1])
        fmt.Println("   URL: ", parts[2])
    }
}

输出(在Go Playground上试试):

Parsing: [Some text](#some/link)
   Text: Some text
   URL:  #some/link
Parsing: [What did I just commit?](#what-did-i-just-commit)
   Text: What did I just commit?
   URL:  #what-did-i-just-commit
Parsing: invalid
   No match!

0
投票

您可以在此用例的pure-Go代码中创建一个简单的词法分析器。多年前Rob Pike有一个great talk进入text/template的设计,这将是适用的。实现将一系列状态函数链接到一个整体状态机中,并通过一个通道(通过Goroutine)将令牌传送出去供以后处理。

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