为什么要学正则表达式?
因为利用正则表达式可以非常方便的匹配我们想要的任何字符串。比如,在一大堆字符串中,我们想找包含“Go语言”并且以“架构师”结尾的所有字符串,利用正则表达式就能非常方便快速的查找出来:
re, _ := regexp.Compile(`Go语言.*架构师`)strs := "kfhewGo语言jiohjnfew.fewujj架构师"fmt.Println(re.FindString(strs)) // 输出:Go语言jiohjnfew.fewujj架构师fmt.Println(re.MatchString(strs)) // 输出:true
一、编译
Go语言的正则表达式在regexp包中。一般,在使用正则表达式之前,我们会把模式字符串编译成正则表达式实例。
regexp.Compile(expr string) (*Regexp, error)
Compile函数会尝试把模式字符串expr编译成正则表达式。什么是模式字符串?也就是本文最开始例子中的“Go语言.*架构师”。这个模式字符串表示先匹配“Go语言”这个字符串,紧接着匹配任意个字符串,最后匹配“架构师”这个字符串。
*Regexp就是返回的编译后的正则表达式实例指针,然后我们可以利用这个正则表达式做很多字符串操作。那么,我们可以写出哪些模式字符串?哪些模式字符串才是合法的?先来看一下模式字符串的语法规则。
语法规则
字符
语法 | 说明 | 表达式示例 | 匹配结果 |
---|---|---|---|
一般字符 | 匹配自身 | abc | abc |
. | 匹配任意除换行符"\n"外的字符, 在 DOTALL 模式中也能匹配换行符 | a.c | abc |
\ | 转义字符,使后一个字符改变原来的意思; 如果字符串中有字符 * 需要匹配,可以使用 \* 或者字符集[*]。 |
a\.c a\\c |
a.c a\c |
[...] | 字符集(字符类),对应的位置可以是字符集中任意字符。 字符集中的字符可以逐个列出,也可以给出范围,如 [abc] 或 [a-c], 第一个字符如果是 ^ 则表示取反,如 [^abc] 表示除了abc之外的其他字符。 |
a[bcd]e | abe 或 ace 或 ade |
\d | 数字:[0-9] | a\dc | a1c |
\D | 非数字:[^\d] | a\Dc | abc |
\s | 空白字符:[\t\r\n\f\v] | a\sc | a c |
\S | 非空白字符:[^\s] | a\Sc | abc |
\w | 单词字符:[A-Za-z0-9] | a\wc | abc |
\W | 非单词字符:[^\w] | a\Wc | a c |
数量词(用在字符或 (...) 之后)
语法 | 说明 | 表达式示例 | 匹配结果 |
---|---|---|---|
* | 匹配前一个字符 0 或无限次 | abc* | ab 或 abccc |
+ | 匹配前一个字符 1 次或无限次 | abc+ | abc 或 abccc |
? | 匹配前一个字符 0 次或 1 次 | abc? | ab 或 abc |
{m} | 匹配前一个字符 m 次 | ab{2}c | abbc |
{m,n} | 匹配前一个字符 m 至 n 次,m 和 n 可以省略,若省略 m,则匹配 0 至 n 次; 若省略 n,则匹配 m 至无限次 |
ab{1,2}c | abc 或 abbc |
边界匹配
语法 | 说明 | 表达式示例 | 匹配结果 |
---|---|---|---|
^ | 匹配字符串开头,在多行模式中匹配每一行的开头 | ^abc | abc |
$ | 匹配字符串末尾,在多行模式中匹配每一行的末尾 | abc$ | abc |
\A | 仅匹配字符串开头 | \Aabc | abc |
\Z | 仅匹配字符串末尾 | abc\Z | abc |
\b | 匹配 \w 和 \W 之间 | a\b!bc | a!bc |
\B | [^\b] |