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  }