regex 用Go匹配任何包含转义字符和换行符的字符串

e3bfsja2  于 2023-06-30  发布在  Go
关注(0)|答案(1)|浏览(126)

文件(C或C++代码)中的任何(格式)字符串,甚至包含转义字符或换行符,都需要通过Go语言编写的工具找到。示例:

..."foo"...
...`foo:"foo"`...
..."foo
foo"...
..."foo\r\nfoo"...
...`foo"foo-

lish`

C/C++解析也允许在注解或停用代码中完成,因此无需排除这些部分。
我成功地
/(["'`])(?:(?=(\?))\2.)*?\1/克
https://regex101.com/r/FDhldb/1上寻找解决方案。
不幸的是,这在Go中无法编译:

const (
patFmtString = `(?Us)(["'])(?:(?=(\\?))\2.)*?\1`
)
var (
matchFmtString = regexp.MustCompile(patFmtString)
)

即使是简化的模式(?Us)(["'])(?:(\\?).)*?\1也会提供“错误解析regexp:转义序列无效:\1”。
我如何在Go中正确地实现它,希望运行得也快?

ewm0tg9j

ewm0tg9j1#

你可以使用一个相当简单的Scanner来完成这个任务,而不是使用PCRE:

import "bufio"

var stringLiterals bufio.SplitFunc = func(data []byte, atEOF bool) (advance int, token []byte, err error) {
    scanning := false
    var delim byte
    var i int
    var start, end int
    for i < len(data) {
        b := data[i]
        switch b {
        case '\\': // skip escape sequences
            i += 2
            continue
        case '"':
            fallthrough
        case '\'':
            fallthrough
        case '`':
            if scanning && delim == b {
                end = i + 1
                token = data[start:end]
                advance = end
                return
            } else if !scanning {
                scanning = true
                start = i
                delim = b
            }
        }
        i++
    }
    if atEOF {
        return len(data), nil, nil
    }
    return start, nil, nil
}

然后用它来

func main() {
    input := /* some reader */
    scanner := bufio.NewScanner(input)
    scanner.Split(stringLiterals)
    for scanner.Scan() {
        stringLit := scanner.Text()
        // do something with `stringLit`
    }
}

对于您的示例,这将返回与正则表达式完全相同的匹配,尽管我不确定这是否与the grammar中定义C++字符串的方式相对应。
你可以在the playground上试试。

相关问题