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

前端之家收集整理的这篇文章主要介绍了正则表达式*和?的一个错误认识前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

这两天再看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:",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",err = regexp.Compile(`\p{Han}?`)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("find: %q\n", -1))
}

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

猜你在找的正则表达式相关文章