github.com/songzhibin97/gkit@v1.2.13/tools/match/match.go (about) 1 package match 2 3 import "unicode/utf8" 4 5 // 基础匹配器 6 // * 匹配任意数字字符 7 // ? 匹配任何一个字符 8 9 // Match 判断是否匹配 10 func Match(str, pattern string) bool { 11 return deepMatch(str, pattern) 12 } 13 14 // deepMatch 深度匹配 15 func deepMatch(str, pattern string) bool { 16 // 如果 pattern 只有 * 直接返回 17 if pattern == "*" { 18 return true 19 } 20 // pattern > 1 的情况 有连续 两个 ** 在一起进行删减 保证 *后面跟其他字符 21 for len(pattern) > 1 && pattern[0] == '*' && pattern[1] == '*' { 22 pattern = pattern[1:] 23 } 24 // 判断 pattern 长度是否有效 25 for len(pattern) > 0 { 26 if pattern[0] > 0x7f { 27 // 0x7f ASCII 最后一位 28 // 如果大于 0x7f 使用 utf-8 rune解析 29 return deepMatchRune(str, pattern) 30 } 31 switch pattern[0] { 32 default: 33 // 如果 待匹配 str 为空 匹配失败 34 if len(str) == 0 { 35 return false 36 } 37 // 如果非ASCII进行rune解析 38 if str[0] > 0x7f { 39 return deepMatchRune(str, pattern) 40 } 41 // 判断str[0] 与 pattern[0] 是否相同 42 if str[0] != pattern[0] { 43 return false 44 } 45 case '?': 46 // 如果是 ? 但是 str 为空则匹配失败 47 if len(str) == 0 { 48 return false 49 } 50 case '*': 51 // 如果是 * 进行递归匹配 52 return deepMatch(str, pattern[1:]) || 53 (len(str) > 0 && deepMatch(str[1:], pattern)) 54 } 55 // str pattern 56 str = str[1:] 57 pattern = pattern[1:] 58 } 59 // 判断 str pattern 是否都匹配到 60 return len(str) == 0 && len(pattern) == 0 61 } 62 63 func deepMatchRune(str, pattern string) bool { 64 if pattern == "*" { 65 return true 66 } 67 for len(pattern) > 1 && pattern[0] == '*' && pattern[1] == '*' { 68 pattern = pattern[1:] 69 } 70 71 var sr, pr rune 72 var srsz, prsz int 73 74 if len(str) > 0 { 75 // 判断如果是rune字节读取 76 // 否则将ASCII转为rune 77 if str[0] > 0x7f { 78 sr, srsz = utf8.DecodeRuneInString(str) 79 } else { 80 sr, srsz = rune(str[0]), 1 81 } 82 } else { 83 // 如果str为空设置为异常码 84 sr, srsz = utf8.RuneError, 0 85 } 86 if len(pattern) > 0 { 87 // str处理同理 88 if pattern[0] > 0x7f { 89 pr, prsz = utf8.DecodeRuneInString(pattern) 90 } else { 91 pr, prsz = rune(pattern[0]), 1 92 } 93 } else { 94 pr, prsz = utf8.RuneError, 0 95 } 96 // done reading 97 for pr != utf8.RuneError { 98 switch pr { 99 default: 100 // 如果另外一个已经读空了 直接返回 101 if srsz == utf8.RuneError { 102 return false 103 } 104 // 判断两个字节是否相同 105 if sr != pr { 106 return false 107 } 108 case '?': 109 // ? 如果另外一个已经读空了 直接返回 110 if srsz == utf8.RuneError { 111 return false 112 } 113 case '*': 114 // * 递归匹配 115 return deepMatchRune(str, pattern[prsz:]) || 116 (srsz > 0 && deepMatchRune(str[srsz:], pattern)) 117 } 118 str = str[srsz:] 119 pattern = pattern[prsz:] 120 // 读取str pattern下一位 121 if len(str) > 0 { 122 if str[0] > 0x7f { 123 sr, srsz = utf8.DecodeRuneInString(str) 124 } else { 125 sr, srsz = rune(str[0]), 1 126 } 127 } else { 128 sr, srsz = utf8.RuneError, 0 129 } 130 if len(pattern) > 0 { 131 if pattern[0] > 0x7f { 132 pr, prsz = utf8.DecodeRuneInString(pattern) 133 } else { 134 pr, prsz = rune(pattern[0]), 1 135 } 136 } else { 137 pr, prsz = utf8.RuneError, 0 138 } 139 } 140 141 return srsz == 0 && prsz == 0 142 } 143 144 var maxRuneBytes = func() []byte { 145 b := make([]byte, 4) 146 if utf8.EncodeRune(b, '\U0010FFFF') != 4 { 147 panic("invalid rune encoding") 148 } 149 return b 150 }() 151 152 // Allowable 返回符合条件的最大值和最小值 153 func Allowable(pattern string) (min, max string) { 154 if pattern == "" || pattern[0] == '*' { 155 return "", "" 156 } 157 158 minB := make([]byte, 0, len(pattern)) 159 maxB := make([]byte, 0, len(pattern)) 160 var wild bool 161 for i := 0; i < len(pattern); i++ { 162 if pattern[i] == '*' { 163 wild = true 164 break 165 } 166 if pattern[i] == '?' { 167 minB = append(minB, 0) 168 maxB = append(maxB, maxRuneBytes...) 169 } else { 170 minB = append(minB, pattern[i]) 171 maxB = append(maxB, pattern[i]) 172 } 173 } 174 if wild { 175 r, n := utf8.DecodeLastRune(maxB) 176 if r != utf8.RuneError { 177 if r < utf8.MaxRune { 178 r++ 179 if r > 0x7f { 180 b := make([]byte, 4) 181 nn := utf8.EncodeRune(b, r) 182 maxB = append(maxB[:len(maxB)-n], b[:nn]...) 183 } else { 184 maxB = append(maxB[:len(maxB)-n], byte(r)) 185 } 186 } 187 } 188 } 189 return string(minB), string(maxB) 190 } 191 192 // IsPattern 判断是否含有 * ? 193 func IsPattern(str string) bool { 194 for i := 0; i < len(str); i++ { 195 if str[i] == '*' || str[i] == '?' { 196 return true 197 } 198 } 199 return false 200 }