golang中的正则表达式使用注意事项与技巧

regexp模块

查看帮助文档:

命令行查看:go doc regexp/syntax

在线查看:

  1. 中文文档 :
    菜鸟教程 介绍一些正则的方法比较详细
    GO语言中文文档对一些难懂的基础语法做了解释,比官方文档更易懂
  2. 英文文档:
    https://pkg.go.dev/regexp go标准库文档,有很多示例。

常用的查询方法

常用查询方法

  1. FindAllString: 完整匹配,仅查询一次,查询到后就返回;
  2. FindString: 完整匹配,可指定查询数量(全部或多个);
  3. FindStringSubmatch :子项查询,获取查询条件中指定的内容。仅查询一次,查询到后就返回;
  4. FindAllStringSubmatch: 子项查询,获取查询条件中指定的内容。可指定查询数量(全部或多个)。

子项查询说明 FindStringSubmatch

注意点:

  1. 使用英文括号包裹需正则中需要获取的内容
  2. 这里使用FindStringSubmatch方法进行搜索。仅查询一次。
func TestFlag5(t *testing.T) {  
   str := `_A_123567abv`                    //要查找的字符串  
   re, _ := regexp.Compile("_\\w_(.*)") //匹配规则  
   fmt.Println(re.FindStringSubmatch(str))  //查询  
}

输出: 第一个元素永远是全部内容,刚开始不习惯,后来发现还是挺好用的

[_A_123567abv 123567abv]

搜索结果中,第一个是正则中完全匹配到的内容。第二个开始才是想要获取的子项。

子项查询说明 FindAllStringSubmatch

分组查询时,在正则表达式中,将需要查询出来的内容用()括起来。

//查询内容
data1 := "type Demo struct {
	Name string `json:\"name\" form:\"name\" gorm:\"column:name;comment: \"`
	Age  int    `json:\"age\" form:\"age\" gorm:\"column:age;comment: \"`
	}"
	
//正则表达式:查询结构体字段、字段类型和json标签中的内容
grep, _ := regexp.Compile(`([\w]{1,})[ ]{1,}([\[\]\w]{2,})[ ]{1,}` + "`" + `(json):"([\w]{1,})[,]{0,}(\w{0,})\"` + ".*`")  

//使用FindAllStringSubmatch函数查询
result := grep.FindAllStringSubmatch(*s.StructValue, -1)

输出结果:

[
[Name string `json:"name" form:"name" gorm:"column:name;comment: "` Name string json name ] [Age  int    `json:"age" form:"age" gorm:"column:age;comment: "` Age int json age ]
]

注意,在这里,每个匹配的搜索结果都单独放在一个切片中。

常见问题与注意事项

  • 转义字符的使用

反引号中使用类似\w(\w代表0-9A-Za-z_)这样的语法不用做任何处理

grep, _ := regexp.Compile(`\w{1,}`)

而在双引号中,反斜杠代表转义符。所以使用\w时,需要额外使用一个\将反斜杠转义为普通字符串,否则报错

grep, _ := regexp.Compile("\\w{1,}")  
  • 替换url

因为url中可能包含特殊字符,所以需要提前对它进行转义。像这样:

re,_ := regexp.Compile(regexp.QuoteMeta(oldStr))

关于最多和最少匹配

python中,最小匹配是有函数可以调用的。而go的regexp模块没有最小匹配的函数。
如果要使用最小匹配,需要配合正则的语法,在文档中介绍在这里

重复:

        x*             重复>=0次匹配x,越多越好(优先重复匹配x)
        x+             重复>=1次匹配x,越多越好(优先重复匹配x)
        x?             0或1次匹配x,优先1次
        x{n,m}         n到m次匹配x,越多越好(优先重复匹配x)
        x{n,}          重复>=n次匹配x,越多越好(优先重复匹配x)
        x{n}           重复n次匹配x
        x*?            重复>=0次匹配x,越少越好(优先跳出重复)
        x+?            重复>=1次匹配x,越少越好(优先跳出重复)
        x??            0或1次匹配x,优先0次
        x{n,m}?        n到m次匹配x,越少越好(优先跳出重复)
        x{n,}?         重复>=n次匹配x,越少越好(优先跳出重复)
        x{n}?          重复n次匹配x

上面的解释中,带有越少越好的就是最小匹配。*+稍有不慎就把全文都给你匹配出来

str := `"老虎大王者荣耀超人"`                   //要查找的字符串  
re := regexp.MustCompile("[\u4e00-\u9fa5]{1,3}") //匹配规则,匹配1到3个中文字符
fmt.Println(re.FindAllString(str, -1)) //查询

输出

[老虎大 王者荣 耀超人]

关于.*? 的坑

在javaScript和python等其它语言中,.*?表示查询所有任意的字符串
而在golang中,文档中是这样说明的

x*?            重复>=0次匹配x,越少越好(优先跳出重复)

注意,重点在于匹配原则是内容越少越好,而正则表达式.*?中的.代表任意字符串(包括空字符串)。

按照这种匹配原则,空字符串总是优先匹配到的,这样就导致了下面的问题:

func TestFlag5(t *testing.T) {  
   data := "你吃饭了吗"  
   grep, _ := regexp.Compile(".*?")  
   result := grep.FindAllString(data, -1)  
   t.Log(result)  
}

输出结果是

structToJson_test.go:107: [     ]

它只匹配到了五个空字符串。

解决方案有两种。第一种,把问号去掉,变成.*即可。 查看文档,(.*的匹配原则是越多越好)

func TestFlag6(t *testing.T) {  
   data1 := "你吃饭了吗"  
   grep, _ := regexp.Compile(".*")//.*?改成了 .*  
   result := grep.FindAllString(data1, -1)  
   t.Log(result)  
}

输出

structToJson_test.go:107: [你吃饭了吗]

第二种方案,.*?后面必须包含字符串

func TestFlag7(t *testing.T) {    
   str := `你吃饭了吗`                      //要查找的字符串  
   re, _ := regexp.Compile(".*?了吗")      //.*?后面加几个字符串,开头加不加无所谓  
   t.Log(re.FindAllString(str, -1)) //查询
}

输出

[你吃饭了吗]

关于匹配中文字符的坑

匹配中文字符这里有个坑,如果匹配规则使用的是双引号,正常输入匹配规则即可

re := regexp.MustCompile("[\u4e00-\u9fa5]{1,}")//匹配规则,\u4e00-\u9fa5表示unicoce中的人一个中文字符

但是如果你使用反引号包裹上面的匹配规则,查询时会导致panic报错

re := regexp.MustCompile(`[\u4e00-\u9fa5]{1,}`)//错误示例

需要写一个双引号包裹的匹配规则,然后赋值粘贴进去,最后变成一串乱码,这才是正确的。

re := regexp.MustCompile(`[一-龥]{1,}`) //匹配规则

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值