wildcard.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Package wildcard 实现了通配符模式匹配功能
  2. package wildcard
  3. const (
  4. normal = iota // 普通字符
  5. all // * 匹配任意数量字符
  6. anySymbol // ? 匹配单个字符
  7. setSymbol // [] 字符集匹配
  8. rangSymbol // [a-b] 范围匹配
  9. negSymbol // [^a] 否定匹配
  10. )
  11. // item 表示模式中的一个元素
  12. type item struct {
  13. character byte // 字符值
  14. set map[byte]bool // 字符集合
  15. typeCode int // 类型码
  16. }
  17. // contains 检查字符是否匹配当前元素
  18. func (i *item) contains(c byte) bool {
  19. switch i.typeCode {
  20. case setSymbol:
  21. _, ok := i.set[c]
  22. return ok
  23. case rangSymbol:
  24. if _, ok := i.set[c]; ok {
  25. return true
  26. }
  27. var (
  28. _min byte = 255
  29. _max byte = 0
  30. )
  31. for k := range i.set {
  32. if _min > k {
  33. _min = k
  34. }
  35. if _max < k {
  36. _max = k
  37. }
  38. }
  39. return c >= _min && c <= _max
  40. case negSymbol:
  41. _, ok := i.set[c]
  42. return !ok
  43. default:
  44. return false
  45. }
  46. }
  47. // Pattern 表示一个通配符模式
  48. type Pattern struct {
  49. items []*item
  50. }
  51. // CompilePattern 将通配符字符串转换为Pattern对象
  52. //
  53. // 支持的通配符:
  54. // * - 匹配任意数量的字符(包括空字符)
  55. // ? - 匹配单个字符
  56. // [] - 匹配括号内任意一个字符,如[abc]
  57. // [a-b] - 匹配范围内的任意字符
  58. // [^a] - 匹配除括号内字符外的任意字符
  59. // \ - 转义字符
  60. func CompilePattern(src string) *Pattern {
  61. items := make([]*item, 0, len(src)) // 预分配容量
  62. escape := false
  63. inSet := false
  64. var set map[byte]bool
  65. for _, v := range src {
  66. c := byte(v)
  67. if escape {
  68. // 处理转义字符
  69. items = append(items, &item{typeCode: normal, character: c})
  70. escape = false
  71. } else if c == '*' {
  72. // 匹配任意数量字符
  73. items = append(items, &item{typeCode: all})
  74. } else if c == '?' {
  75. // 匹配单个字符
  76. items = append(items, &item{typeCode: anySymbol})
  77. } else if c == '\\' {
  78. // 转义下一个字符
  79. escape = true
  80. } else if c == '[' {
  81. // 开始字符集定义
  82. if !inSet {
  83. inSet = true
  84. set = make(map[byte]bool)
  85. } else {
  86. set[c] = true
  87. }
  88. } else if c == ']' {
  89. // 结束字符集定义
  90. if inSet {
  91. inSet = false
  92. typeCode := setSymbol
  93. if _, ok := set['-']; ok {
  94. typeCode = rangSymbol
  95. delete(set, '-')
  96. }
  97. if _, ok := set['^']; ok {
  98. typeCode = negSymbol
  99. delete(set, '^')
  100. }
  101. items = append(items, &item{typeCode: typeCode, set: set})
  102. } else {
  103. items = append(items, &item{typeCode: normal, character: c})
  104. }
  105. } else {
  106. if inSet {
  107. set[c] = true
  108. } else {
  109. items = append(items, &item{typeCode: normal, character: c})
  110. }
  111. }
  112. }
  113. return &Pattern{
  114. items: items,
  115. }
  116. }
  117. // IsMatch 检查给定字符串是否匹配该模式
  118. // 使用动态规划算法实现
  119. func (p *Pattern) IsMatch(s string) bool {
  120. if len(p.items) == 0 {
  121. return len(s) == 0
  122. }
  123. m := len(s)
  124. n := len(p.items)
  125. // 使用二维布尔数组进行动态规划
  126. table := make([][]bool, m+1)
  127. for i := range table {
  128. table[i] = make([]bool, n+1)
  129. }
  130. // 初始化基本情况
  131. table[0][0] = true
  132. // 处理空字符串与模式的匹配情况
  133. for j := 1; j <= n; j++ {
  134. if p.items[j-1].typeCode == all {
  135. table[0][j] = table[0][j-1]
  136. }
  137. }
  138. // 填充动态规划表
  139. for i := 1; i <= m; i++ {
  140. for j := 1; j <= n; j++ {
  141. switch p.items[j-1].typeCode {
  142. case all:
  143. // * 可以匹配空字符串或多个字符
  144. table[i][j] = table[i-1][j] || table[i][j-1]
  145. case anySymbol:
  146. // ? 匹配任意单个字符
  147. table[i][j] = table[i-1][j-1]
  148. case normal:
  149. // 普通字符精确匹配
  150. table[i][j] = table[i-1][j-1] && s[i-1] == p.items[j-1].character
  151. default:
  152. // 集合类匹配 [abc], [a-z], [^a] 等
  153. table[i][j] = table[i-1][j-1] && p.items[j-1].contains(s[i-1])
  154. }
  155. }
  156. }
  157. return table[m][n]
  158. }