feat:Add like pattern matching syntax

This commit is contained in:
rulego-team
2025-06-16 19:45:12 +08:00
parent 193e616636
commit 95bc6fed4f
11 changed files with 1708 additions and 20 deletions
+72 -1
View File
@@ -1,6 +1,8 @@
package condition
import (
"fmt"
"github.com/expr-lang/expr"
"github.com/expr-lang/expr/vm"
)
@@ -14,7 +16,24 @@ type ExprCondition struct {
}
func NewExprCondition(expression string) (Condition, error) {
program, err := expr.Compile(expression)
// 添加自定义字符串函数支持startsWith、endsWith、contains是内置操作符
options := []expr.Option{
expr.Function("like_match", func(params ...any) (any, error) {
if len(params) != 2 {
return false, fmt.Errorf("like_match function requires 2 parameters")
}
text, ok1 := params[0].(string)
pattern, ok2 := params[1].(string)
if !ok1 || !ok2 {
return false, fmt.Errorf("like_match function requires string parameters")
}
return matchesLikePattern(text, pattern), nil
}),
expr.AllowUndefinedVariables(),
expr.AsBool(),
}
program, err := expr.Compile(expression, options...)
if err != nil {
return nil, err
}
@@ -28,3 +47,55 @@ func (ec *ExprCondition) Evaluate(env interface{}) bool {
}
return result.(bool)
}
// matchesLikePattern 实现LIKE模式匹配
// 支持%匹配任意字符序列和_匹配单个字符
func matchesLikePattern(text, pattern string) bool {
return likeMatch(text, pattern, 0, 0)
}
// likeMatch 递归实现LIKE匹配算法
func likeMatch(text, pattern string, textIndex, patternIndex int) bool {
// 如果模式已经匹配完成
if patternIndex >= len(pattern) {
return textIndex >= len(text) // 文本也应该匹配完成
}
// 如果文本已经结束,但模式还有非%字符,则不匹配
if textIndex >= len(text) {
// 检查剩余的模式是否都是%
for i := patternIndex; i < len(pattern); i++ {
if pattern[i] != '%' {
return false
}
}
return true
}
// 处理当前模式字符
patternChar := pattern[patternIndex]
if patternChar == '%' {
// %可以匹配0个或多个字符
// 尝试匹配0个字符跳过%
if likeMatch(text, pattern, textIndex, patternIndex+1) {
return true
}
// 尝试匹配1个或多个字符
for i := textIndex; i < len(text); i++ {
if likeMatch(text, pattern, i+1, patternIndex+1) {
return true
}
}
return false
} else if patternChar == '_' {
// _匹配恰好一个字符
return likeMatch(text, pattern, textIndex+1, patternIndex+1)
} else {
// 普通字符必须精确匹配
if text[textIndex] == patternChar {
return likeMatch(text, pattern, textIndex+1, patternIndex+1)
}
return false
}
}