不支持的 Perl 语法:“(?<”

我想解析cmd “gpg --列表键”的结果,以在浏览器上显示它。厘米输出如下:



    pub   rsa3072 2021-08-03 [SC] [expires: 2023-08-03]

          07C47E284765D5593171C18F00B11D51A071CB55

    uid           [ultimate] user1 <user1@example.com>

    sub   rsa3072 2021-08-03 [E] [expires: 2023-08-03]

    

    pub   rsa3072 2021-08-04 [SC]

          37709ABD4D96324AB8CBFC3B441812AFBCE7A013

    uid           [ultimate] user2 <user2@example.com>

    sub   rsa3072 2021-08-04 [E]


我期望这样的事情:



    {

        {uid : user1@example.com},

        {uid : user2@example.com},

    }


代码如下:


    type GPGList struct{

        uid string

    }

    

    //find list keys

    func Findlistkeys(){

        pathexec, _ := exec.LookPath("gpg")

        cmd := exec.Command(pathexec, "--list-keys")

        cmdOutput := &bytes.Buffer{}

        cmd.Stdout = cmdOutput

        printCommand(cmd)

        err := cmd.Run()

        printError(err)

        output := cmdOutput.Bytes()

        printOutput(output)

        GPG := GPGList{}

        parseOutput(output, &GPG)

        fmt.Println(GPG)

    }

    

    func printCommand(cmd *exec.Cmd) {

        fmt.Printf("==> Executing: %s\n", strings.Join(cmd.Args, " "))

    }

    

    func printError(err error) {

        if err != nil {

                os.Stderr.WriteString(fmt.Sprintf("==> Error: %s\n", err.Error()))

        }

    }

    

    func printOutput(outs []byte) {

        if len(outs) > 0 {

                fmt.Printf("==> Output: %s\n", string(outs))

        }

    }

    

    func parseOutput(outs []byte, GPG *GPGList) {

        var uid = regexp.MustCompile(`(?<=\<)(.*?)(?=\>)`)

        fmt.Println(uid)

    }

它以以下消息结尾:


    panic: regexp: Compile(`(?<=\<)(.*?)(?=\>)`): error parsing regexp: invalid or unsupported Perl syntax: `(?<

到目前为止,我正在与正则表达式堆叠。它不明白为什么它不想编译...这是怎么回事?


我已经在在线模拟器上测试了正则表达式,它看起来还不错,但是它有问题。有什么建议吗?


万千封印
浏览 245回答 3
3回答

慕的地8271018

这是另一个基于机器可读输出的解决方案。gpg --list-keys --with-colons它仍然是一个缓慢的解决方案,但易于编写,易于更新,不使用正则表达式。一个聪明的人可以带来一个更快的解决方案,而不会增加一个疯狂的复杂性墙。(只需循环遍历字符串,直到捕获字符串,直到<>)这是基于一个简单的csv阅读器,因此您可以将其插入到命令的输出流中。执行实例,或其他任何内容。最大的优点是它不需要缓冲内存中的整个数据,它可以流解码。package mainimport (&nbsp; &nbsp; "encoding/csv"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "io"&nbsp; &nbsp; "regexp"&nbsp; &nbsp; "strings")func main() {&nbsp; &nbsp; fmt.Printf("%#v\n", extractEmailsCSV(csvInput))}var uid = regexp.MustCompile(`\<(.*?)\>`)func extractEmailsRegexp(input string) (out []string) {&nbsp; &nbsp; submatchall := uid.FindAllString(input, -1)&nbsp; &nbsp; for _, element := range submatchall {&nbsp; &nbsp; &nbsp; &nbsp; element = strings.Trim(element, "<")&nbsp; &nbsp; &nbsp; &nbsp; element = strings.Trim(element, ">")&nbsp; &nbsp; &nbsp; &nbsp; out = append(out, element)&nbsp; &nbsp; }&nbsp; &nbsp; return}func extractEmailsCSV(input string) (out []string) {&nbsp; &nbsp; r := strings.NewReader(input)&nbsp; &nbsp; csv := csv.NewReader(r)&nbsp; &nbsp; csv.Comma = ':'&nbsp; &nbsp; csv.ReuseRecord = true&nbsp; &nbsp; csv.FieldsPerRecord = -1&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; records, err := csv.Read()&nbsp; &nbsp; &nbsp; &nbsp; if err == io.EOF {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; &nbsp; &nbsp; } else if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if len(records) < 10 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; r := records[9]&nbsp; &nbsp; &nbsp; &nbsp; if strings.Contains(r, "@") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin := strings.Index(r, "<")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end := strings.Index(r, ">")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if begin+end > 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; out = append(out, r[begin+1:end])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return}var regexpInput = `&nbsp; &nbsp; pub&nbsp; &nbsp;rsa3072 2021-08-03 [SC] [expires: 2023-08-03]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 07C47E284765D5593171C18F00B11D51A071CB55&nbsp; &nbsp; uid&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[ultimate] user1 <user1@example.com>&nbsp; &nbsp; sub&nbsp; &nbsp;rsa3072 2021-08-03 [E] [expires: 2023-08-03]&nbsp; &nbsp; pub&nbsp; &nbsp;rsa3072 2021-08-04 [SC]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 37709ABD4D96324AB8CBFC3B441812AFBCE7A013&nbsp; &nbsp; uid&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[ultimate] user2 <user2@example.com>&nbsp; &nbsp; sub&nbsp; &nbsp;rsa3072 2021-08-04 [E]`var csvInput = `pub:u:1024:17:51FF9A17136C5B87:1999-04-24::59:-:Tony Nelson <tnelson@techie.com>:uid:u::::::::Tony Nelson <tnelson@conceptech.com>:`我们没有完全相同的基准测试设置,但无论如何。如果您认为它膨胀了比较,请随时提供更好的工作台设置。这是基准测试设置package mainimport (&nbsp; &nbsp; "strings"&nbsp; &nbsp; "testing")func BenchmarkCSV_1(b *testing.B) {&nbsp; &nbsp; input := strings.Repeat(csvInput, 1)&nbsp; &nbsp; b.ResetTimer()&nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; _ = extractEmailsCSV(input)&nbsp; &nbsp; }}func BenchmarkRegExp_1(b *testing.B) {&nbsp; &nbsp; input := strings.Repeat(regexpInput, 1)&nbsp; &nbsp; b.ResetTimer()&nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; _ = extractEmailsRegexp(input)&nbsp; &nbsp; }}func BenchmarkCSV_10(b *testing.B) {&nbsp; &nbsp; input := strings.Repeat(csvInput, 10)&nbsp; &nbsp; b.ResetTimer()&nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; _ = extractEmailsCSV(input)&nbsp; &nbsp; }}func BenchmarkRegExp_10(b *testing.B) {&nbsp; &nbsp; input := strings.Repeat(regexpInput, 10)&nbsp; &nbsp; b.ResetTimer()&nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; _ = extractEmailsRegexp(input)&nbsp; &nbsp; }}func BenchmarkCSV_100(b *testing.B) {&nbsp; &nbsp; input := strings.Repeat(csvInput, 100)&nbsp; &nbsp; b.ResetTimer()&nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; _ = extractEmailsCSV(input)&nbsp; &nbsp; }}func BenchmarkRegExp_100(b *testing.B) {&nbsp; &nbsp; input := strings.Repeat(regexpInput, 100)&nbsp; &nbsp; b.ResetTimer()&nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; _ = extractEmailsRegexp(input)&nbsp; &nbsp; }}这是结果BenchmarkCSV_1BenchmarkCSV_1-4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 242736&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4200 ns/op&nbsp; &nbsp; &nbsp; &nbsp; 5072 B/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;18 allocs/opBenchmarkRegExp_1BenchmarkRegExp_1-4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;252232&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4466 ns/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;400 B/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 allocs/opBenchmarkCSV_10BenchmarkCSV_10-4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 68257&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;17335 ns/op&nbsp; &nbsp; &nbsp; &nbsp; 7184 B/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;40 allocs/opBenchmarkRegExp_10BenchmarkRegExp_10-4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;29871&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;39947 ns/op&nbsp; &nbsp; &nbsp; &nbsp; 3414 B/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;68 allocs/opBenchmarkCSV_100BenchmarkCSV_100-4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7538&nbsp; &nbsp; &nbsp; &nbsp; 141609 ns/op&nbsp; &nbsp; &nbsp; &nbsp;25872 B/op&nbsp; &nbsp; &nbsp; &nbsp; 223 allocs/opBenchmarkRegExp_100BenchmarkRegExp_100-4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1726&nbsp; &nbsp; &nbsp; &nbsp; 674718 ns/op&nbsp; &nbsp; &nbsp; &nbsp;37858 B/op&nbsp; &nbsp; &nbsp; &nbsp; 615 allocs/op在原始速度和分配方面,正则表达式在小数据集上更好,尽管只要有一点点数据,正则表达式就会变慢并且分配更多因素。另见 https://pkg.go.dev/testing我的结论是,不要使用正则表达式...此外,优化正则表达式即使不是不可能,也是困难的,因为优化算法以解析某些文本输入是可行的,如果不是那么容易。总而言之,如果没有一个深思熟虑的程序员来驱动它,即使是最快和最好的运行时也算不了什么。

哔哔one

所以我更新了正则表达式...但是由于正在研究在线模拟器,我真的很惊讶。为什么正则表达式不能在所有语言中都一样工作...(?<=\<)(.*?)(?=\>)&nbsp; &nbsp; func parseOutput(outs []byte, GPG *GPGList) {&nbsp; &nbsp; &nbsp; &nbsp; var uid = regexp.MustCompile(`\<(.*?)\>`)&nbsp; &nbsp; &nbsp; &nbsp; submatchall := uid.FindAllString(string(outs), -1)&nbsp; &nbsp; &nbsp; &nbsp; for _, element := range submatchall {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element = strings.Trim(element, "<")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element = strings.Trim(element, ">")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(element)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }

qq_花开花谢_0

正则表达式包使用 RE2 接受的语法。从&nbsp;https://github.com/google/re2/wiki/Syntax(?<=re) 后的文本匹配 re (不支持)因此,错误消息:解析正则表达式时出错: 无效或不受支持的 Perl 语法:(?<在线模拟器可能正在测试不同的正则表达式语法。您将需要找到替代的正则表达式编码或不同的正则表达式包。您可以尝试的替代编码是(游乐场)。这很简单,可能与您的原始意图不符。\<([^\>]*)\>
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go