浅析 Regular Expression (正则表达式)
I. 何谓正则表达式
正则表达式(Regular Expression,常简写为 regex、regexp、RE),又称规律表达式、模式表达式、正则表达式、常规表达式,是计算机科学概念,用简单字符串来描述、匹配文中全部匹配指定格式的字符串,现在很多文本编辑器都支持用正则表达式搜索、取代匹配指定格式的字符串。
总之, Regex 是一种小型的、高度专业化的编程语言, 它被用来检索、替换那些符合某个模式(规则)的文本。
一个正则表达式通常被称为一个模式(pattern),为用来描述或者匹配一系列匹配某个句法规则的字符串.
正则表达式是由普通字符(例如字符 a
到 z
)以及特殊字符(称为 “元字符” )组成的文字模式。
模式描述在搜索文本时要匹配的一个或多个字符串。
正则表达式作为一个模板, 将某个字符模式与所搜索的字符串进行匹配。
II. 普通字符 与 元字符
模式 | 描述 | 正则表达式 | 匹配项 |
---|---|---|---|
普通字符 a ~ z |
匹配自身 | abc |
abc |
. |
匹配除换行符 \n 以外的任意字符 |
a.c |
abc / acc / awc |
\ |
转义字符,使后一个字符改变原来的意思 | a\.c;a\\c |
a.c;a\c |
* |
匹配前一个字符 0 次或多次 | a*c |
ac / c / aaaaac |
+ |
匹配前一个字符 1 次或多次 | a+c |
ac / aac / aaaaac |
? |
匹配前一个字符 0 次或 1 次 | a?c |
ac / c |
^ |
匹配字符串开头,在多行模式中匹配每一行的开头 | ^ab |
ab |
$ |
匹配字符串结尾,在多行模式中匹配每一行的结尾 | ab$ |
ab |
| |
或,匹配 | 左右任意一个表达式,从左向右匹配,若没有 | 包括在 () 中,则匹配整个表达式 |
abc|def |
abc / def |
{} |
{m} 匹配前一个字符 m 次,{m,n} 匹配前一个字符 m 到 n 次 |
a{2}c |
aac |
[] |
字符集合,匹配方括号中包含的任意一个字符: 字符可以逐个列出,也可给出范围,所有特殊字符在字符集中都失去其原有的特殊含义(使用 \ 转义恢复其特殊含义) |
[abc] |
a / b / c |
() |
分组,将括号中字符作为一个整体,可以用来匹配括号中的字符 | (abc) |
abc |
- 反斜杠
\
后边跟元字符去除特殊含义,即特殊字符普通化 - 反斜杠
\
后边跟普通字符实现特殊功能,即普通字符特殊化,亦称预定义字符 - 引用序号对应的字组成所匹配的字符串
III. 预定义字符
预定义字符集是指在正则表达式中具有特殊意义的专用字符集,如 \d
、\w
、\s
等,可以写在方括号 []
中,也可以单独使用。
模式 | 描述 | 正则表达式 | 匹配项 |
---|---|---|---|
\d |
匹配一个数字,等价于 [0-9] |
a\dc |
a1c / a2c / a3c |
\D |
匹配一个非数字,等价于 [^0-9] |
a\Dc |
a-c / a$c |
\s |
匹配一个空白字符,包括空格、制表符、换页符和换行符,等价于 [ \f\n\r\t\v] |
a\sc |
a c / a\tc / a\nc |
\S |
匹配一个非空白字符,等价于 [^ \f\n\r\t\v] / [^\s] |
a\Sc |
a$c / a-c |
\w |
匹配一个单字字符(字母、数字或者下划线),等价于 [A-Za-z0-9_] |
a\wc |
a1c / abc / a_c |
\W |
匹配一个非单字字符,即特殊字符,等价于 [^A-Za-z0-9_] |
a\Wc |
a$c / a-c |
\A |
仅匹配字符串开头,等价于 ^ |
\Aabc |
abc |
\Z |
仅匹配字符串结尾,等价于 $ |
abc\Z |
abc |
\b |
匹配一个单词边界,即字与空格间的位置 | \babc\b |
<space> |
\B |
匹配非单词边界,等价于 [^\b] |
a\Bbc |
abc |
IV. 特殊分组
特殊分组是指在正则表达式中具有特殊意义的专用分组,如 (?P<name>...)
、(?P=name)
、(?#...)
、(?=...)
、(?!...)
、(?<=...)
、(?<!...)
等,可以写在方括号 []
中,也可以单独使用。
模式 | 描述 | 正则表达式 | 匹配项 |
---|---|---|---|
(?P<name>...) |
为分组起一个别名,匹配的字符串可以通过 \g<name> 或 \k<name> 引用 |
(?P<name>abc) |
abc |
(?P=name) |
引用别名为 name 的分组匹配的字符串 | (?P<id>\d)abc(?P=id) |
1abc1 / 2abc2 |
\<number> |
通过 \g<number> 或 \k<number> 引用编号为 number 的分组匹配的字符串 |
`(\d)abc\1 | 1abc / 2abc |
V. match
、search
与findall
1. match
match
方法用于查找字符串的头部(也可以指定起始位置),它是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果。
2. search
search
方法用于查找字符串的任何位置,它也是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果。
3. findall
findall
方法用于查找字符串所有(非重复)的匹配子串,返回一个列表,如果没有找到匹配的,则返回空列表。
VI. 贪婪匹配与惰性匹配
1. 贪婪匹配
正则表达式一般趋向于最大长度匹配,即匹配直到下一个字符不满足匹配规则为止,这被称为贪婪匹配。
例如,*
通常意味着匹配零个或多个字符(包括零个),+
通常意味着匹配一个或多个字符(包括一个),?
通常意味着匹配零个或一个字符,{m,n}
通常意味着匹配 m 到 n 个字符。
2. 惰性匹配
惰性匹配,即匹配尽可能少的字符。在贪婪匹配符号后面加上一个问号 ?
就可以实现惰性匹配。