123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- package main
- import (
- "fmt"
- "regexp"
- "strings"
- )
- type RuleDetail struct {
- RuleRaw string
- RequiredMatched []string
- ExcludedMatched []string
- Matched bool
- }
- type MatchResult struct {
- Matched bool
- MatchedRules []string
- FailedRules []string
- Details []RuleDetail
- }
- func parseRule(rule string) (required []string, minCount int, excluded []string) {
- rule = strings.TrimSpace(rule)
- if strings.Contains(rule, "^") {
- // 复合规则 (A|B|C)N^(X|Y|Z)
- re := regexp.MustCompile(`^\(([^)]+)\)(\d+)\^\(([^)]+)\)$`)
- matches := re.FindStringSubmatch(rule)
- if len(matches) != 4 {
- panic("复合规则格式错误:" + rule)
- }
- required = strings.Split(matches[1], "|")
- minCount = atoi(matches[2])
- excluded = strings.Split(matches[3], "|")
- } else {
- // 简单规则 (A|B|C)
- re := regexp.MustCompile(`^\(([^)]+)\)$`)
- matches := re.FindStringSubmatch(rule)
- if len(matches) != 2 {
- panic("简单规则格式错误:" + rule)
- }
- required = strings.Split(matches[1], "|")
- minCount = 1
- excluded = nil
- }
- return
- }
- func atoi(s string) int {
- var i int
- fmt.Sscanf(s, "%d", &i)
- return i
- }
- func matchSingleRule(text string, rule string) RuleDetail {
- required, minCount, excluded := parseRule(rule)
- detail := RuleDetail{
- RuleRaw: rule,
- }
- for _, kw := range required {
- if strings.Contains(text, kw) {
- detail.RequiredMatched = append(detail.RequiredMatched, kw)
- }
- }
- for _, ex := range excluded {
- if strings.Contains(text, ex) {
- detail.ExcludedMatched = append(detail.ExcludedMatched, ex)
- }
- }
- detail.Matched = len(detail.RequiredMatched) >= minCount && len(detail.ExcludedMatched) == 0
- return detail
- }
- func MatchAllRules(text string, ruleStr string) MatchResult {
- rules := splitRules(ruleStr)
- res := MatchResult{}
- for _, rule := range rules {
- detail := matchSingleRule(text, rule)
- res.Details = append(res.Details, detail)
- if detail.Matched {
- res.MatchedRules = append(res.MatchedRules, rule)
- } else {
- res.FailedRules = append(res.FailedRules, rule)
- }
- }
- res.Matched = len(res.MatchedRules) > 0
- return res
- }
- // 支持用逗号分割时括号内可能也有逗号的情况
- func splitRules(s string) []string {
- var res []string
- start := 0
- level := 0
- for i, c := range s {
- if c == '(' {
- level++
- } else if c == ')' {
- level--
- } else if c == ',' && level == 0 {
- res = append(res, strings.TrimSpace(s[start:i]))
- start = i + 1
- }
- }
- res = append(res, strings.TrimSpace(s[start:]))
- return res
- }
|