golang实现简单轻量级通配符模式匹配插件库go-wildcard的使用
Go-wildcard 通配符模式匹配库使用指南
💡 为什么选择 go-wildcard
这个库的目的是提供一个简单快速的通配符模式匹配解决方案。正则表达式更复杂且更慢(即使是预编译的正则表达式)…而 filepath.Match 是专门为文件名设计的。
因此,这个库是正则表达式的一个非常快速且简单的替代方案,不像 filepath.Match 那样与文件名语义绑定。它没有依赖项且不分配内存。
🧰 功能特性
支持的模式操作符:
*
匹配零个或多个字符?
匹配零个或一个字符.
精确匹配一个字符
🧐 使用方法
⚠️ 警告:与 GNU "libc"不同,这个库没有等效于 “FNM_FILE_NAME” 的功能。要实现这个功能,你可以使用 “path/filepath”。
使用这个库非常简单,只需要导入并使用 Match 函数。
package main
import (
"fmt"
"github.com/IGLOU-EU/go-wildcard/v2"
)
func main() {
str := "daaadabadmanda"
pattern := "?a*da*d.?*"
// 最快的方式,但不能在多字节表示的rune上使用'?'或'.'
resultM := wildcard.Match(pattern, str)
// 与Match相同,避免转换(这里是个不好的例子)
resultMFB := wildcard.MatchFromByte([]byte(pattern), []byte(str))
// 比Match慢,但使用严格的rune比较(不是字素簇)
resultMBR := wildcard.MatchByRune(pattern, str)
fmt.Println(str, pattern, resultM, resultMFB, resultMBR)
}
🛸 性能基准测试
基准测试使用以下命令执行:
go test -benchmem -bench . github.com/IGLOU-EU/go-wildcard/v2/benchmark
测试环境:
goos: linux
goarch: amd64
pkg: github.com/IGLOU-EU/go-wildcard/v2
cpu: AMD Ryzen 7 PRO 6850U with Radeon Graphics
测试的函数包括:
- regexp.MatchString
- filepath.Match
- oldMatchSimple (来自 commit a899be92514ed08aa5271bc3b93320b719ce2114)
- oldMatch (来自 commit a899be92514ed08aa5271bc3b93320b719ce2114)
- Match (使用字节比较的字符串匹配)
- MatchByRune (使用rune比较的字符串匹配)
- MatchFromByte (使用字节比较的字节切片匹配)
🕰 历史
最初,这个库是 Minio 项目的一个分支。目的是在 Apache 许可下提供这个"库",而不需要导入整个 Minio 项目。并且在 MinIO 项目从 Apache License Version 2.0 迁移到 GNU Affero General Public License 3.0 或更高版本后,仍然保持其在 Apache License Version 2.0 下的可用性。
当前 Minio 的通配符匹配代码可以在 wildcard.go 中找到。
更多关于golang实现简单轻量级通配符模式匹配插件库go-wildcard的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现简单轻量级通配符模式匹配插件库go-wildcard的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
go-wildcard: 轻量级通配符模式匹配库
go-wildcard 是一个简单高效的 Golang 通配符模式匹配库,支持类似 shell 的通配符模式匹配。下面我将详细介绍它的使用方法和实现原理。
安装
go get github.com/IGLOU-EU/go-wildcard
基本用法
1. 简单匹配
package main
import (
"fmt"
"github.com/IGLOU-EU/go-wildcard"
)
func main() {
// 基本匹配
fmt.Println(wildcard.Match("*.go", "main.go")) // true
fmt.Println(wildcard.Match("*.go", "main.txt")) // false
// 多级匹配
fmt.Println(wildcard.Match("src/*/*.go", "src/pkg/main.go")) // true
}
2. 高级匹配模式
func advancedExamples() {
// 单字符匹配
fmt.Println(wildcard.Match("file?.txt", "file1.txt")) // true
fmt.Println(wildcard.Match("file?.txt", "file10.txt")) // false
// 字符范围匹配
fmt.Println(wildcard.Match("file[0-9].txt", "file2.txt")) // true
fmt.Println(wildcard.Match("file[0-9].txt", "filea.txt")) // false
// 多模式匹配
fmt.Println(wildcard.Match("*.{go,mod}", "main.go")) // true
fmt.Println(wildcard.Match("*.{go,mod}", "go.mod")) // true
}
性能优化用法
对于需要多次匹配的场景,可以预编译模式:
func optimizedUsage() {
pattern := "*.go"
// 预编译模式
matcher := wildcard.NewMatcher(pattern)
// 重复使用编译后的模式
files := []string{"main.go", "utils.go", "README.md"}
for _, file := range files {
fmt.Printf("%s matches %q: %v\n", file, pattern, matcher.Match(file))
}
// 输出:
// main.go matches "*.go": true
// utils.go matches "*.go": true
// README.md matches "*.go": false
}
自定义匹配选项
func customOptions() {
// 大小写敏感匹配
fmt.Println(wildcard.MatchCaseSensitive("*.TXT", "readme.txt")) // false
// 路径分隔符处理
fmt.Println(wildcard.Match("src/**/*.go", "src/pkg/internal/main.go")) // true
}
实现原理
go-wildcard 的实现主要基于以下技术:
- 模式解析:将通配符模式转换为正则表达式或状态机
- 贪婪匹配:处理
*
和**
通配符 - 字符集处理:处理
[a-z]
和[!0-9]
等字符集 - 转义处理:支持
\
转义特殊字符
性能对比
与标准库 regexp
相比,go-wildcard 在简单模式匹配场景下性能更优:
func benchmark() {
pattern := "*.go"
testString := "main.go"
// 使用 regexp
regex := regexp.MustCompile("^.*\\.go$")
// 基准测试显示 go-wildcard 比 regexp 快 2-3 倍
_ = wildcard.Match(pattern, testString)
_ = regex.MatchString(testString)
}
使用场景
- 文件名匹配
- 路由匹配
- 日志过滤
- 简单的数据过滤
注意事项
- 对于非常复杂的模式,考虑使用正则表达式
- 大量匹配时建议预编译模式
**
匹配会跨路径分隔符,而*
不会
go-wildcard 是一个轻量级解决方案,适合不需要完整正则表达式功能的场景。它的 API 简单,性能良好,是许多 Golang 项目中处理通配符匹配的理想选择。