Go 的regexp
包提供的规则表达式的支持,至于可使用的规则表达式,在regexp/syntax
有说明。
在 Go 中要编写规则表达式,使用反引号(`)是比较方便的做法,这样就不用转译\
。
诠译字符在规则表达式中有特殊意义,例如$ ^ * ( ) + = { } [ ] | \ : . ?
等,若要比对这些字符,则必须加上转义(Escape)符号,即使 Python 有原始字符串表示,自己处理这些事也还是麻烦,这时可以使用regexp
的QuoteMeta
函数来代劳:
func QuoteMeta(s string) string
例如:
fmt.Println(regexp.QuoteMeta(`main.exe`)) // main\.exe
在regexp
包中提供其他函数,主要就是比对来源中,是否有符合规则表达式的部份,来源可以是[]byte
、io.RuneReader
或者是string
,比对结果会是布尔值,若是规则表达式有误,错误就不会是nil
:
func Match(pattern string, b []byte) (matched bool, err error)
func MatchReader(pattern string, r io.RuneReader) (matched bool, err error)
func MatchString(pattern string, s string) (matched bool, err error)
例如:
package main
import (
"fmt"
"regexp"
)
func main() {
matched, err := regexp.MatchString(`\d{3}`, "Kaohsiung 803, Road 12")
fmt.Println(matched, err)
matched, err = regexp.MatchString(`\d{4}-\d{6}`, "0970-168168")
fmt.Println(matched, err)
matched, err = regexp.MatchString(`\d{4}-\d{6}`, "Phone: 0970-168168")
fmt.Println(matched, err)
}
可以在规则表达式中使用嵌入标志表示法(Embedded Flag Expression)。例如(?i)dog
,表示不区分大小写,若想对特定分组嵌入标志,可以使用(?i:dog)
这样的语法。
至于 Go 中可用的 POSIX 字符类:
- [[:alnum:]]:字母与数字(等于 [0-9A-Za-z])
- [[:alpha:]]:字母(等于 [A-Za-z])
- [[:ascii:]]:ASCII(等于 [\x00-\x7F])
- [[:blank:]]:空白或 Tab(等于 [\t ])
- [[:cntrl:]]:控制字符(等于 [\x00-\x1F\x7F])
- [[:digit:]]:数字(等于 [0-9])
- [[:graph:]]:可见字符(等于 [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_{|}~]`)
- [[:lower:]]:小写字母(等于 [a-z])
- [[:print:]]:可打印字符(等于 [ -~]、[ [:graph:]])
- [[:punct:]]:标点符号(等于 [!-/:-@[-{-~]`)
- [[:space:]]:全部的空白(等于 [\t\n\v\f\r ])
- [[:upper:]]:大写(等于 [A-Z])
- [[:word:]]:单字字符(等于 [0-9A-Za-z_])
- [[:xdigit:]]:十六进制数字(等于 [0-9A-Fa-f])
在Unicode 特性的支持上,使用\p
、\P
的方式,表示具有或不具有指定的特性,\pN
、\PN
的N
是单一字母,若要多个字母组合,可以使用\p{...}
、\P{...}
。
例如〈一般分类特性〉,\pL
表示字母(Letter),\pN
表示数字(Number)等,若要进一步指定子特性,例如\p{Lu}
表示大写字母、\p{Ll}
表示小写字母:
fmt.Println(regexp.MatchString(`\p{Ll}`, "a")) // true <nil>
fmt.Println(regexp.MatchString(`\p{Lu}`, "a")) // false <nil>
来个有趣的比对吧!𝟏𝟐𝟑𝟜𝟝𝟞𝟩𝟪𝟫𝟬𝟭𝟮𝟯𝟺𝟻𝟼
都是十进制数字:
fmt.Println(regexp.MatchString(`\p{Nd}`, "𝟏𝟐𝟑𝟜𝟝𝟞𝟩𝟪𝟫𝟬𝟭𝟮𝟯𝟺𝟻𝟼")) // true <nil>
数字呢?²³¹¼½¾𝟏𝟐𝟑𝟜𝟝𝟞𝟩𝟪𝟫𝟬𝟭𝟮𝟯𝟺𝟻𝟼㉛㉜㉝ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫⅬⅭⅮⅯⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹⅺⅻⅼⅽⅾⅿ
都是:
fmt.Println(regexp.MatchString(`\p{N}`, "²³¹¼½¾𝟏𝟐𝟑𝟜𝟝𝟞𝟩𝟪𝟫𝟬𝟭𝟮𝟯𝟺𝟻𝟼㉛㉜㉝ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫⅬⅭⅮⅯⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹⅺⅻⅼⅽⅾⅿ")) // true <nil>
有的语言可能会使用多种文本来书写,例如日语就包含了汉字、平假名、片假名等文本,有的语言只使用一种文本,例如泰文。Unicode 将码群组为文本(script)特性上,测试时只要写上文本特性名称就可以了,例如测试汉字、希腊文:
fmt.Println(regexp.MatchString(`\p{Han}`, "林")) // true <nil>
fmt.Println(regexp.MatchString(`\p{Greek}`, "α")) // true <nil>