Sscanf 没有正确匹配单引号

Sscanf not properly matching single quotes

我正在处理一些 Go 代码,但我无法弄清楚为什么我的字符串没有被正确扫描。

我得到一个如下所示的字符串:

"ERROR: 1: something happened 'here'"

我正在尝试这样扫描它:

n, err := fmt.Sscanf("ERROR: 1: something happened 'here'", "ERROR: 1: something happened '%50s'", &value)

但是,每次检查值的结果时,我都会得到这样的结果:

here'

最后一个单引号的位置。

知道如何解决这个问题吗?我认为这种情况不会是不确定的,因为如果不包含引号,该函数将无法完成格式化。

当然,我可以简单地删除最后一个字符,但我更喜欢基于 fmt 的解决方案。

内置 fmt.Scanner 无法执行您想要执行的操作。如果目标文本用双引号引起来,您可以使用 %q 说明符。

或者,如果目标是单个换行字符,您可以使用 text/scanner。但是因为你的目标不是这些,所以没有内置任何东西。所以,你的选择是 regexp,或者 bufio 使用自定义扫描仪,甚至只是 strings.Split。如果你坚持使用 fmt 你可以做一个自定义扫描仪,但这可能是最糟糕的选择:

package main
import "fmt"

type quote struct { tok string }

func (q *quote) Scan(state fmt.ScanState, verb rune) error {
   tok, err := state.Token(false, func(r rune) bool {
      return r != 0x27 // '
   })
   if err != nil {
      return err
   }
   if _, _, err := state.ReadRune(); err != nil {
      if len(tok) == 0 {
         panic(err)
      }
   }
   q.tok = string(tok)
   return nil
}

示例:

package main

import (
   "fmt"
   "strings"
)

func main() {
   r := strings.NewReader("ERROR: 1: something happened 'here'")
   for {
      var q quote
      _, err := fmt.Fscan(r, &q)
      if err != nil {
         break
      }
      fmt.Printf("%q\n", q.tok)
   }
}

结果:

"ERROR: 1: something happened "
"here"