3 回答
TA贡献1796条经验 获得超4个赞
这是另一个基于机器可读输出的解决方案。gpg --list-keys --with-colons
它仍然是一个缓慢的解决方案,但易于编写,易于更新,不使用正则表达式。
一个聪明的人可以带来一个更快的解决方案,而不会增加一个疯狂的复杂性墙。(只需循环遍历字符串,直到捕获字符串,直到<>)
这是基于一个简单的csv阅读器,因此您可以将其插入到命令的输出流中。执行实例,或其他任何内容。
最大的优点是它不需要缓冲内存中的整个数据,它可以流解码。
package main
import (
"encoding/csv"
"fmt"
"io"
"regexp"
"strings"
)
func main() {
fmt.Printf("%#v\n", extractEmailsCSV(csvInput))
}
var uid = regexp.MustCompile(`\<(.*?)\>`)
func extractEmailsRegexp(input string) (out []string) {
submatchall := uid.FindAllString(input, -1)
for _, element := range submatchall {
element = strings.Trim(element, "<")
element = strings.Trim(element, ">")
out = append(out, element)
}
return
}
func extractEmailsCSV(input string) (out []string) {
r := strings.NewReader(input)
csv := csv.NewReader(r)
csv.Comma = ':'
csv.ReuseRecord = true
csv.FieldsPerRecord = -1
for {
records, err := csv.Read()
if err == io.EOF {
break
} else if err != nil {
panic(err)
}
if len(records) < 10 {
continue
}
r := records[9]
if strings.Contains(r, "@") {
begin := strings.Index(r, "<")
end := strings.Index(r, ">")
if begin+end > 0 {
out = append(out, r[begin+1:end])
}
}
}
return
}
var regexpInput = `
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]
`
var csvInput = `pub:u:1024:17:51FF9A17136C5B87:1999-04-24::59:-:Tony Nelson <tnelson@techie.com>:
uid:u::::::::Tony Nelson <tnelson@conceptech.com>:
`
我们没有完全相同的基准测试设置,但无论如何。如果您认为它膨胀了比较,请随时提供更好的工作台设置。
这是基准测试设置
package main
import (
"strings"
"testing"
)
func BenchmarkCSV_1(b *testing.B) {
input := strings.Repeat(csvInput, 1)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = extractEmailsCSV(input)
}
}
func BenchmarkRegExp_1(b *testing.B) {
input := strings.Repeat(regexpInput, 1)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = extractEmailsRegexp(input)
}
}
func BenchmarkCSV_10(b *testing.B) {
input := strings.Repeat(csvInput, 10)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = extractEmailsCSV(input)
}
}
func BenchmarkRegExp_10(b *testing.B) {
input := strings.Repeat(regexpInput, 10)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = extractEmailsRegexp(input)
}
}
func BenchmarkCSV_100(b *testing.B) {
input := strings.Repeat(csvInput, 100)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = extractEmailsCSV(input)
}
}
func BenchmarkRegExp_100(b *testing.B) {
input := strings.Repeat(regexpInput, 100)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = extractEmailsRegexp(input)
}
}
这是结果
BenchmarkCSV_1
BenchmarkCSV_1-4 242736 4200 ns/op 5072 B/op 18 allocs/op
BenchmarkRegExp_1
BenchmarkRegExp_1-4 252232 4466 ns/op 400 B/op 9 allocs/op
BenchmarkCSV_10
BenchmarkCSV_10-4 68257 17335 ns/op 7184 B/op 40 allocs/op
BenchmarkRegExp_10
BenchmarkRegExp_10-4 29871 39947 ns/op 3414 B/op 68 allocs/op
BenchmarkCSV_100
BenchmarkCSV_100-4 7538 141609 ns/op 25872 B/op 223 allocs/op
BenchmarkRegExp_100
BenchmarkRegExp_100-4 1726 674718 ns/op 37858 B/op 615 allocs/op
在原始速度和分配方面,正则表达式在小数据集上更好,尽管只要有一点点数据,正则表达式就会变慢并且分配更多因素。
另见 https://pkg.go.dev/testing
我的结论是,不要使用正则表达式...此外,优化正则表达式即使不是不可能,也是困难的,因为优化算法以解析某些文本输入是可行的,如果不是那么容易。
总而言之,如果没有一个深思熟虑的程序员来驱动它,即使是最快和最好的运行时也算不了什么。
TA贡献1854条经验 获得超8个赞
所以我更新了正则表达式...但是由于正在研究在线模拟器,我真的很惊讶。为什么正则表达式不能在所有语言中都一样工作...(?<=\<)(.*?)(?=\>)
func parseOutput(outs []byte, GPG *GPGList) {
var uid = regexp.MustCompile(`\<(.*?)\>`)
submatchall := uid.FindAllString(string(outs), -1)
for _, element := range submatchall {
element = strings.Trim(element, "<")
element = strings.Trim(element, ">")
fmt.Println(element)
}
}
TA贡献1835条经验 获得超7个赞
正则表达式包使用 RE2 接受的语法。从 https://github.com/google/re2/wiki/Syntax
(?<=re) 后的文本匹配 re (不支持)
因此,错误消息:
解析正则表达式时出错: 无效或不受支持的 Perl 语法:
(?<
在线模拟器可能正在测试不同的正则表达式语法。您将需要找到替代的正则表达式编码或不同的正则表达式包。
您可以尝试的替代编码是(游乐场)。这很简单,可能与您的原始意图不符。\<([^\>]*)\>
- 3 回答
- 0 关注
- 106 浏览
添加回答
举报