正则表达式*和?的一个错误认识

这两天再看go的正则表达式的时候,看到关于unicode匹配的方式\p{Name}不是很明白,所以就想写程序来尝试一下,因此而引出博文标题提到的一个误区。
首先还是先解释下\p{name}到底是什么意思。
这里的{name}指的是unicode的类型对象名称,具体可在RE2 syntax中查看。其中{Han}可以用来匹配中文字符,因此下了下面的程序来验证。

package main
import (
    "fmt"
    "regexp"
)

func main() {
    re, err := regexp.Compile(`\p{Han}*`)
    if err != nil {
        fmt.Println(err)
        return
    }
    s := "foo中文哦test"
    fmt.Println(re.FindString(s))
}

出乎意料的是上面的程序输出的是空,而我希望的是输出中文哦
然后对上面的程序进行了修改

package main

import (
    "fmt"
    "regexp"
)

func main() {
    s := "foo中文哦woqu"

    re, err := regexp.Compile(`\p{Han}*`)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println("find:", re.FindString(s))

    re, err = regexp.Compile(`\p{Han}+`)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println("find:", re.FindString(s))

    re, err = regexp.Compile(`\p{Han}?`)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println("find:", re.FindString(s))
}

这段程序有如下输出:
find:
find: 中文哦
find:
这就让我疑惑了,因为从文档查看到

  • x* zero or more x, prefer more
  • x+ one or more x, prefer more
  • x? zero or one x, prefer one
    所以为什么不是按照如下输出的呢:
    find: 中文哦
    find: 中文哦
    find: 中
    后来通过提问和搜索,终于找到了原因,

原因正是因为*除了匹配尽可能多的字符,还有一个特点就是也会匹配zero x,因为find只会查找到第一个匹配的字符,因此在*的情况下,第一个匹配到的都是空字符串,而+因为至少匹配一个,所以其匹配到的是中文哦
我们可以通过findAllString来验证一下:

package main

import (
    "fmt"
    "regexp"
)

func main() {
    s := "foo中文哦woqu"

    re, err := regexp.Compile(`\p{Han}*`)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("find: %q\n", re.FindAllString(s, -1))

    re, err = regexp.Compile(`\p{Han}+`)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("find: %q\n", re.FindAllString(s, -1))

    re, err = regexp.Compile(`\p{Han}?`)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("find: %q\n", re.FindAllString(s, -1))
}

这段程序输出了:
find: [“” “” “” “中文哦” “” “” “” “”]
find: [“中文哦”]
find: [“” “” “” “中” “文” “哦” “” “” “” “”]
正好验证了我的猜测。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值