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

String 解析Go中的格式化字符串,string,go,String,Go,问题 我有一片字符串值,其中每个值都是基于模板格式化的。在我的特殊情况下,我尝试解析标记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 conf

问题

我有一片
字符串
值,其中每个值都是基于模板格式化的。在我的特殊情况下,我尝试解析标记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字段没有根据此规则填充

如何获得上面提到的降价值

编辑:根据马克的建议,我将添加几个澄清点:


  • 这是一个关于基于格式解析字符串的通用问题。在我的特殊情况下,标记解析器可能会对我有所帮助,但我的目的是学习如何在库可能不存在的情况下处理这种情况
  • 在这里发布之前,我已经阅读了官方文件

  • 注意:以下解决方案仅适用于“简单”的非转义输入标记链接。如果这适合你的需要,就去使用它吧。为了实现完全的标记兼容性,您应该使用适当的标记解析器,例如


    您可以使用regexp从标记链接中获取链接文本和URL

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

    [some text](somelink)
    
    对此建模的正则表达式:

    \[([^\]]+)\]\(([^)]+)\)
    
    其中:

    • \[
      是文本
      [
    • ([^\]]+)
      代表
      “一些文本”
      ,除了结束方括号外,它是所有内容
    • \]
      是文本
      ]
    • \(
      是文本
    • ([^)]+)
      是用于
      的“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])
        }
    }
    
    输出(在上尝试):


    注意:以下解决方案仅适用于“简单”的非转义输入标记链接。如果这适合你的需要,就去使用它吧。为了实现完全的标记兼容性,您应该使用适当的标记解析器,例如


    您可以使用regexp从标记链接中获取链接文本和URL

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

    [some text](somelink)
    
    对此建模的正则表达式:

    \[([^\]]+)\]\(([^)]+)\)
    
    其中:

    • \[
      是文本
      [
    • ([^\]]+)
      代表
      “一些文本”
      ,除了结束方括号外,它是所有内容
    • \]
      是文本
      ]
    • \(
      是文本
    • ([^)]+)
      是用于
      的“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代码中创建一个简单的lexer。罗布·派克(Rob Pike)几年前的一篇文章将其应用到设计中。该实现将一系列状态函数链接到一个整体状态机中,并通过一个通道(通过Goroutine)将令牌发送出去以供以后处理。

    您可以使用纯Go代码为该用例创建一个简单的lexer。罗布·派克(Rob Pike)几年前的一篇文章将其应用到设计中。该实现将一系列状态函数链接到一个整体状态机中,并通过一个通道(通过Goroutine)将令牌发送出去以供以后处理。

    有什么原因不能使用现有的标记解析器吗?这是一个关于解析给定格式的字符串的通用问题。我认为降价解析器对于我的任务来说是一种过分的手段。此外,不能保证始终存在合适的解析器。好的,那么请阅读,它清楚地说明:“%s动词(…)在第一个空格或换行符处停止使用输入”。然后它就找不到
    ]
    ,因此永远无法解析URL。您不应该忽略来自
    Sscanf
    的返回。谢谢您的建议。在询问之前,我确实阅读了文档,我在这篇文章中也提到了“不能保证始终存在一个合适的解析器”-您只是想通过使用regexp来实现这一点吗?有什么理由不能使用现有的markdown解析器吗?这是一个关于解析给定格式的字符串的通用问题。我认为降价解析器对于我的任务来说是一种过分的手段。此外,不能保证始终存在合适的解析器。好的,那么请阅读,它清楚地说明:“%s动词(…)在第一个空格或换行符处停止使用输入”。然后它就找不到
    ]
    ,因此永远无法解析URL。您不应该忽略来自
    Sscanf
    的返回。谢谢您的建议。在询问之前,我确实阅读了文档,我在这篇文章中也提到过。“不能保证合适的解析器会一直存在”-你只是想通过使用regexp来完成这一点吗?这对OP列出的示例很有用。但是请注意,
    [\[foo\]](foo.com)
    是有效的标记。@Marc你说得对,我忘了。我添加了一条说明。这对OP列出的示例有效。但请注意,
    [\[foo\]](foo.com)
    是有效的标记。@Marc你说得对,我忘了这一点。我加了一张便条提到这一点。