Go语言regexp包


Go语言 regexp标准包 为正则表达式提供官方支持 在Go语言环境中 使用 go doc regexp/syntax 命令查看正则表达式 语法
Go语言regexp包存放位置 \Go\src\regexp

Regexp正则对象

Regexp 是一个编译好的正则表达式对象
type Regexp struct { // read-only after Compile
  regexpRO
  // cache of machines for running regexp
  mu   sync.Mutex
  machine []*machine
}
通常需要使用正则表达式构建一个正则对象

regexp常用接口

func Match(pattern string, b []byte) (matched bool, err error)
func MatchString(pattern string, s string) (matched bool, err error)
func MatchReader(pattern string, r io.RuneReader) (matched bool, err error)
判断b中能否找到pattern所匹配的字符串
func Compile(expr string) (*Regexp, error)
将正则表达式编译成正则对象(使用PERL语法)
该正则对象会采用leftmost-first模式选择第一个匹配结果
如果正则表达式语法错误 则返回错误信息
func CompilePOSIX(expr string) (*Regexp, error)
将正则表达式编译成一个正则对象(正则语法限制在 POSIX ERE 范围内)
该正则对象会采用 “leftmost-longest” 模式选择最长的匹配结果
POSIX 语法不支持Perl的语法格式:\d、\D、\s、\S、\w、\W
如果正则表达式语法错误 则返回错误信息
func MustCompile(str string) *Regexp
func MustCompilePOSIX(str string) *Regexp
将正则表达式编译成一个正则对象 但会在解析失败时panic
func (re *Regexp) Longest()
让正则表达式在之后的搜索中都采用“leftmost-longest”模式
func (re *Regexp) String() string
返回编译时使用的正则表达式字符串
func (re *Regexp) NumSubexp() int
返回正则表达式中分组的数量
func (re *Regexp) SubexpNames() []string
返回正则表达式中分组的名字
第 0 个元素表示整个正则表达式的名字 永远是空字符串
func (re *Regexp) LiteralPrefix() (prefix string, complete bool)
返回正则表达式必须匹配到的字面前缀(不包含可变部分)
如果整个正则表达式都是字面值 则 complete 返回 true
package main
import (
  "regexp"
  "fmt"
)
var mailRegexp = regexp.MustCompile(`([A-Za-z0-9]+)@([A-Za-z0-9.]+)\.([A-Za-z0-9.]+)`)
func main() {
  s := " hello's email is hellogo@gmail.com"
  matches := mailRegexp.FindStringSubmatch(s)
  fmt.Println(matches)// [hellogo@gmail.com hellogo gmail com]
  fmt.Println(matches[0]) // hellogo@gmail.com
  fmt.Println(matches[1]) // hellogo
  fmt.Println(matches[2]) // gmail
  fmt.Println(matches[3]) // com
}

Go正则表达式搜索

package regexp
import "regexp"
regexp包实现了正则表达式搜索
正则表达式采用 RE2语法(除了\c、\C) 和Perl Python等语言的正则基本一致
参见 http://code.google.com/p/re2/wiki/Syntax
本包采用的正则表达式语法 默认采用perl标志 某些语法 通过切换解析时的标志来关闭

单字符

  .     任意字符(标志s==true时还包括换行符)
 [xyz]    字符族
 [^xyz]   反向字符族
 \d    Perl预定义字符族
 \D    反向Perl预定义字符族
 [:alpha:]   ASCII字符族
 [:^alpha:]  反向ASCII字符族
 \pN    Unicode字符族(单字符名)见unicode包
 \PN    反向Unicode字符族(单字符名)
 \p{Greek}   Unicode字符族(完整字符名)
 \P{Greek}   反向Unicode字符族(完整字符名)

结合

 xy    匹配x后接着匹配y
 x|y    匹配x或y(优先匹配x)

重复

 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

实现的限制

计数格式x{n}等(不包括x*等格式)中n最大值1000 负数或者显式出现的过大的值  导致解析错误 返回ErrInvalidRepeatSize

分组

 (re) 编号的捕获分组
 (?P<name>re)  命名并编号的捕获分组
 (?:re)   不捕获的分组
 (?flags)   设置当前所在分组的标志 不捕获也不匹配
 (?flags:re)  设置re段的标志 不捕获的分组

标志的语法为xyz

(设置)、-xyz(清楚)、xy-z(设置xy,清楚z),标志如下
 I     大小写敏感(默认关闭)
 m     ^和$在匹配文本开始和结尾之外 可以匹配行首和行尾(默认开启)
 s     让.可以匹配\n(默认关闭)
 U     非贪婪的:交换x*和x*?、x+和x+?……的含义 默认关闭

边界匹配

 ^     匹配文本开始,标志m为真时,还匹配行首
 $     匹配文本结尾,标志m为真时,还匹配行尾
 \A    匹配文本开始
 \b    单词边界(一边字符属于\w,另一边为文首、文尾、行首、行尾或属于\W)
 \B    非单词边界
 \z    匹配文本结尾

转义序列

 \a    响铃符(\007)
 \f    换纸符(\014)
 \t    水平制表符(\011)
 \n    换行符(\012)
 \r    回车符(\015)
 \v    垂直制表符(\013)
 \123    八进制表示的字符码(最多三个数字)
 \x7F    十六进制表示的字符码(必须两个数字)
 \x{10FFFF}  十六进制表示的字符码
 \*    字面值'*'
 \Q...\E   反斜线后面的字符的字面值

字符族

(预定义字符族之外,方括号内部)的语法
 x     单个字符
 A-Z    字符范围(方括号内部才可以用)
 \d    Perl字符族
 [:foo:]   ASCII字符族
 \pF    单字符名的Unicode字符族
 \p{Foo}   完整字符名的Unicode字符族

预定义字符族作为字符族的元素

 [\d]    == \d
 [^\d]    == \D
 [\D]    == \D
 [^\D]    == \d
 [[:name:]]  == [:name:]
 [^[:name:]]  == [:^name:]
 [\p{Name}]  == \p{Name}
 [^\p{Name}]  == \P{Name}

Perl字符族

 \d    == [0-9]
 \D    == [^0-9]
 \s    == [\t\n\f\r ]
 \S    == [^\t\n\f\r ]
 \w    == [0-9A-Za-z_]
 \W    == [^0-9A-Za-z_]

ASCII字符族

 [:alnum:]   == [0-9A-Za-z]
 [:alpha:]   == [A-Za-z]
 [:ascii:]   == [\x00-\x7F]
 [:blank:]   == [\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]
本包的正则表达式保证搜索复杂度为O(n)其中n为输入的长度 这一点 其他开源实现 无法保证 见 http://swtch.com/~rsc/regexp/regexp1.html
或其他关于自动机理论  所有 字符 为utf-8编码的码值
Regexp类型提供了多达16个方法
用于匹配正则表达式并获取匹配的结果  名字满足如下正则表达式
Find(All)?(String)?(Submatch)?(Index)?
如果'All'出现了 该方法会返回输入中所有互不重叠的匹配结果 如果一个匹配结果的前后(没有间隔字符)存在长度为0的成功匹配
该空匹配会被忽略 包含All的方法会要求一个额外的整数参数n,如果n>=0,方法会返回最多前n个匹配结果
如果 String 出现了 匹配对象为字符串 否则应该是[]byte类型 返回值和匹配对象的类型是对应的
如果 Submatch 出现了 返回值是表示正则表达式中成功的组匹配(子匹配/次级匹配)的切片 组匹配是正则表达式内部的括号包围的次级表达式(也称为“捕获分组"
从左到右按左括号的顺序编号 索引0的组匹配为完整表达式的匹配结果 1为第一个分组的匹配结果,依次类推
如果'Index'出现了 匹配/分组匹配会用输入流的字节索引对表示result[2*n:2*n+1]表示第n个分组匹配的的匹配结果 如果没有'Index'
匹配结果表示为匹配到的文本 如果索引为负数 表示分组匹配没有匹配到输入流中的文本
方法集也有一个用于从RuneReader中读取文本进行匹配的子集
MatchReader, FindReaderIndex, FindReaderSubmatchIndex
该子集可能会增加 注意正则表达式匹配可能需要检验匹配结果前后的文本
因此从RuneReader匹配文本的方法很可能会读取到远远超出返回的结果所在的位置
另有几个其他方法不满足该方法模式的
// Compile the expression oce, usually at init time
// Use raw strings to avoid having to quote the backslashes
var validID = regexp.MustCompile(`^[a-z]+\[[0-9]+\]$`)
fmt.Println(validID.MatchString("adam[23]"))//true
fmt.Println(validID.MatchString("eve[7]"))//true
fmt.Println(validID.MatchString("Job[48]"))//false
fmt.Println(validID.MatchString("snakey"))//false

package syntax

import "regexp/syntax"
Package syntax parses regular expressions into parse trees and compiles parse trees into programs. Most clients of regular expressions will use the facilities of package regexp (such as Compile and Match) instead of this package
Syntax
The regular expression syntax understood by this package when parsing with the Perl flag is as follows. Parts of the syntax can be disabled by passing alternate flags to Parse

Single characters


.     any character, possibly including newline (flag s=true)
[xyz]    character class
[^xyz]   negated character class
\d    Perl character class
\D    negated Perl character class
[[:alpha:]]  ASCII character class
[[:^alpha:]]  negated ASCII character class
\pN    Unicode character class (one-letter name)
\p{Greek}   Unicode character class
\PN    negated Unicode character class (one-letter name)
\P{Greek}   negated Unicode character class

Composites

xy    x followed by y
x|y    x or y (prefer x)

Repetitions

x*    zero or more x, prefer more
x+    one or more x, prefer more
x?    zero or one x, prefer one
x{n,m}   n or n+1 or ... or m x, prefer more
x{n,}    n or more x, prefer more
x{n}    exactly n x
x*?    zero or more x, prefer fewer
x+?    one or more x, prefer fewer
x??    zero or one x, prefer zero
x{n,m}?   n or n+1 or ... or m x, prefer fewer
x{n,}?   n or more x, prefer fewer
x{n}?    exactly n x
Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n} reject forms that create a minimum or maximum repetition count above 1000. Unlimited repetitions are not subject to this restriction

Grouping

(re)    numbered capturing group (submatch)
(?P<name>re)  named & numbered capturing group (submatch)
(?:re)   non-capturing group
(?flags)   set flags within current group; non-capturing
(?flags:re)  set flags during re; non-capturing

Flag syntax is xyz

(set) or -xyz (clear) or xy-z (set xy, clear z). The flags are
i     case-insensitive (default false)
m     multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false)
s     let . match \n (default false)
U     ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false)

Empty strings

^     at beginning of text or line (flag m=true)
$     at end of text (like \z not Perl's \Z) or line (flag m=true)
\A    at beginning of text
\b    at ASCII word boundary (\w on one side and \W, \A, or \z on the other)
\B    not at ASCII word boundary
\z    at end of text

Escape sequences

\a    bell (== \007)
\f    form feed (== \014)
\t    horizontal tab (== \011)
\n    newline (== \012)
\r    carriage return (== \015)
\v    vertical tab character (== \013)
\*    literal *, for any punctuation character *
\123    octal character code (up to three digits)
\x7F    hex character code (exactly two digits)
\x{10FFFF}  hex character code
\Q...\E   literal text ... even if ... has punctuation

Character class elements

x     single character
A-Z    character range (inclusive)
\d    Perl character class
[:foo:]   ASCII character class foo
\p{Foo}   Unicode character class Foo
\pF    Unicode character class F (one-letter name)

Named character classes as character class elements

[\d]    digits (== \d)
[^\d]    not digits (== \D)
[\D]    not digits (== \D)
[^\D]    not not digits (== \d)
[[:name:]]  named ASCII class inside character class (== [:name:])
[^[:name:]]  named ASCII class inside negated character class (== [:^name:])
[\p{Name}]  named Unicode property inside character class (== \p{Name})
[^\p{Name}]  named Unicode property inside negated character class (== \P{Name})

Perl character classes (all ASCII-only)

\d    digits (== [0-9])
\D    not digits (== [^0-9])
\s    whitespace (== [\t\n\f\r ])
\S    not whitespace (== [^\t\n\f\r ])
\w    word characters (== [0-9A-Za-z_])
\W    not word characters (== [^0-9A-Za-z_])

ASCII character classes

[[:alnum:]]  alphanumeric (== [0-9A-Za-z])
[[:alpha:]]  alphabetic (== [A-Za-z])
[[:ascii:]]  ASCII (== [\x00-\x7F])
[[:blank:]]  blank (== [\t ])
[[:cntrl:]]  control (== [\x00-\x1F\x7F])
[[:digit:]]  digits (== [0-9])
[[:graph:]]  graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
[[:lower:]]  lower case (== [a-z])
[[:print:]]  printable (== [ -~] == [ [:graph:]])
[[:punct:]]  punctuation (== [!-/:-@[-`{-~])
[[:space:]]  whitespace (== [\t\n\v\f\r ])
[[:upper:]]  upper case (== [A-Z])
[[:word:]]  word characters (== [0-9A-Za-z_])
[[:xdigit:]]  hex digit (== [0-9A-Fa-f])

Go 正则表达式和regexp相关