golang中的星号*通配符字符串模式匹配 和问号? 通配符字符串模式匹配的2种实现方法 和相关的单元测试用例

在go语言中,我们如果需要对字符串进行星号* 或者问号? 模式匹配, 可以有2种方法实现 通配符 * 问号 ? 匹配, 找出给定的输入字符串str是否与pattern字符串模式相匹配。

模式匹配函数使用文档参考 strutils package - github.com/tekintian/strutils - Go Packages

下面分别对这2种实现方式进行说明

1. 正则实现* ?通配符模式匹配

  通过将字符串中的* ?通配符转换为对应的正则后利用正则表达式进行字符串匹配,实现代码如下:


// 星号模式匹配* 和问号模式匹配 ,将模式匹配字符串转换为正则后使用正则进行匹配
// @author: tekintian@gmail.com
// @see https://dev.tekin.cn
// @docs 使用文档 https://pkg.go.dev/github.com/tekintian/strutils#IsWmMatchingReg
func IsWmMatchingReg(str, pattern string) bool {
	// 模式匹配符 *, ? 转换为正则表达式, *替换为 (.*?), .需要进行转义为 \. ; 问号?转换为 (.?)
	rp := strings.NewReplacer("*", `(.*?)`, ".", `\.`, "?", `(.?)`)
	reg := rp.Replace(pattern) // 将v转换为正则表达式
	// 如果正则中不包含前后限定符,则添加上
	if !strings.HasPrefix(reg, "^") && !strings.HasSuffix(reg, "$") {
		reg = fmt.Sprintf(`^%s$`, reg) // 在正则中增加前后限定符
	}
	// 正则对象获取
	regex, err := GetRegexp(reg)
	if err != nil {
		return false
	}
	// 正则匹配
	return regex.MatchString(str)
}

详细使用文档和示例代码参考 strutils package - github.com/tekintian/strutils - Go Packages 

2. 使用二维矩阵matrix方式实现模式匹配

通过创建一个二维矩阵matrix,其中matrix[i][j] 如果输入字符串中的第一个i字符与模式中的第一个j字符匹配,则为真。 这种方式效果和第一种正则的方式是一样的,只不过代码稍微复杂了一些。

func IsWmMatching(str string, pattern string) bool {
	rstrs := []rune(str)
	rpats := []rune(pattern)

	lenInput := len(rstrs)
	lenPattern := len(rpats)

	// 创建一个二维矩阵matrix,其中matrix[i][j] 如果输入字符串中的第一个i字符与模式中的第一个j字符匹配,则为真。
	matrix := make([][]bool, lenInput+1)

	for i := range matrix {
		matrix[i] = make([]bool, lenPattern+1)
	}

	matrix[0][0] = true
	for i := 1; i < lenInput; i++ {
		matrix[i][0] = false
	}

	if lenPattern > 0 {
		if rpats[0] == '*' {
			matrix[0][1] = true
		}
	}

	for j := 2; j <= lenPattern; j++ {
		if rpats[j-1] == '*' {
			matrix[0][j] = matrix[0][j-1]
		}

	}
	for i := 1; i <= lenInput; i++ {
		for j := 1; j <= lenPattern; j++ {

			if rpats[j-1] == '*' {
				matrix[i][j] = matrix[i-1][j] || matrix[i][j-1]
			}

			if rpats[j-1] == '?' || rstrs[i-1] == rpats[j-1] {
				matrix[i][j] = matrix[i-1][j-1]
			}
		}
	}
	return matrix[lenInput][lenPattern]
}

单元测试用例


func TestIsWmMatchingReg(t *testing.T) {
	testCases := []struct {
		str     string
		pattern string
		ret     bool
	}{
		{str: "https://www.tekin.cn", pattern: "*.tekin.cn", ret: true},
		{str: "dev.tekin.cn", pattern: "www.tekin.cn", ret: false},
		{str: "dev.tekin.cx", pattern: "dev.tekin.c?", ret: true},
		{str: "dev.tekin.cxxyy", pattern: "dev.tekin.c?", ret: false},
	}
	for _, v := range testCases {
		// ret := strutils.IsWmMatching(v.str, v.pattern)
		ret := strutils.IsWmMatchingReg(v.str, v.pattern)
		if ret != v.ret {
			t.Fatalf("failed to match %v, expected %v, got %v", v.str, v.ret, ret)
		}
	}

}

总结:字符串的通配符* ?模式匹配的重点关注于对字符串的模式/格式进行验证,可以应用在对字符串的模式进行验证的场景,如CORS中的origin安全验证等场景,我们可以通过通配符来批量对允许的origin进行设置和验证,从而可以规避CORS的通配符和访问认证的相关问题。

CORS参考 http跨域网络请求中的CORS(跨源资源共享) 那些事 -- HTTP跨域请求, chrome插件跨域请求使用详解, origin格式,origin通配符等-CSDN博客

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值