github.com/hdt3213/godis@v1.2.9/lib/wildcard/wildcard.go (about) 1 package wildcard 2 3 import ( 4 "errors" 5 "regexp" 6 "strings" 7 ) 8 9 // Pattern represents a wildcard pattern 10 type Pattern struct { 11 exp *regexp.Regexp 12 } 13 14 var replaceMap = map[byte]string{ 15 // characters in the wildcard that must be escaped in the regexp 16 '+': `\+`, 17 ')': `\)`, 18 '$': `\$`, 19 '.': `\.`, 20 '{': `\{`, 21 '}': `\}`, 22 '|': `\|`, 23 '*': ".*", 24 '?': ".", 25 } 26 27 var errEndWithEscape = "end with escape \\" 28 29 // CompilePattern convert wildcard string to Pattern 30 func CompilePattern(src string) (*Pattern, error) { 31 regexSrc := strings.Builder{} 32 regexSrc.WriteByte('^') 33 for i := 0; i < len(src); i++ { 34 ch := src[i] 35 if ch == '\\' { 36 if i == len(src)-1 { 37 return nil, errors.New(errEndWithEscape) 38 } 39 regexSrc.WriteByte(ch) 40 regexSrc.WriteByte(src[i+1]) 41 i++ // skip escaped character 42 } else if ch == '^' { 43 if i == 0 { 44 regexSrc.WriteString(`\^`) 45 } else if i == 1 { 46 if src[i-1] == '[' { 47 regexSrc.WriteString(`^`) // src is: [^ 48 } else { 49 regexSrc.WriteString(`\^`) 50 } 51 } else { 52 if src[i-1] == '[' && src[i-2] != '\\' { 53 regexSrc.WriteString(`^`) // src is: [^, except \[^ 54 } else { 55 regexSrc.WriteString(`\^`) 56 } 57 } 58 } else if escaped, toEscape := replaceMap[ch]; toEscape { 59 regexSrc.WriteString(escaped) 60 } else { 61 regexSrc.WriteByte(ch) 62 } 63 } 64 regexSrc.WriteByte('$') 65 re, err := regexp.Compile(regexSrc.String()) 66 if err != nil { 67 return nil, err 68 } 69 return &Pattern{ 70 exp: re, 71 }, nil 72 } 73 74 // IsMatch returns whether the given string matches pattern 75 func (p *Pattern) IsMatch(s string) bool { 76 return p.exp.Match([]byte(s)) 77 }