正则表达式
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符").
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串.
正则表达式的使用
- 测试字符串内的模式.例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式.这称为数据验证.
- 替换文本.可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它.
- 基于模式匹配从字符串中提取子字符串.可以查找文档内或输入域内特定的文本.
1. 正则表达式语法
1.1 非打印字符
| 字符 | 描述 |
|---|---|
| `cx` | 匹配由x指明的控制字符.例如,\cM 匹配一个 Control-M 或回车符.x 的值必须为 A-Z 或 a-z 之一.否则,将 c 视为一个原义的 'c' 字符 |
\f |
匹配一个换页符.等价于 \x0c 和 \cL |
\n |
匹配一个换行符.等价于 \x0a 和 \cJ |
\r |
匹配一个回车符.等价于 \x0d 和 \cM |
\s |
匹配任何空白字符,包括空格、制表符、换页符等等.等价于 [ \f\n\r\t\v] |
\S |
匹配任何非空白字符.等价于 \f\n\r\t\v |
\t |
匹配一个制表符.等价于 \x09 和 \cI |
\v |
匹配一个垂直制表符.等价于 \x0b 和 \cK |
1.2 特殊字符
所谓特殊字符,就是一些有特殊含义的字符,比如*,简单的说就是表示任何字符串的意思.如果要查找字符串中的*符号,则需要对*进行转义,即\*.
许多元字符要求在试图匹配它们时特别对待.若要匹配这些特殊字符,必须首先使字符"转义",即,将反斜杠字符\ 放在它们前面.
| 特殊字符 | 描述 |
|---|---|
$ |
匹配输入字符串的结尾位置.如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'.要匹配 $ 字符本身,请使用 $ |
() |
标记一个子表达式的开始和结束位置.子表达式可以获取供以后使用.要匹配这些字符,请使用 ( 和 ) |
* |
匹配前面的子表达式零次或多次.要匹配 字符,请使用 \ |
+ |
匹配前面的子表达式一次或多次.要匹配 + 字符,请使用 + |
. |
匹配除换行符 \n 之外的任何单字符.要匹配 . ,请使用 . |
[ |
标记一个中括号表达式的开始.要匹配 [,请使用[ |
? |
匹配前面的子表达式零次或一次,或指明一个非贪婪限定符.要匹配 ? 字符,请使用 \? |
\ |
将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符.例如,'n' 匹配字符 'n'.'\n' 匹配换行符.序列 '\' 匹配 "\",而 '(' 则匹配 "(" |
^ |
匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合.要匹配 ^ 字符本身,请使用 \^ |
{ |
标记限定符表达式的开始.要匹配 {,请使用 { |
| | | 指明两项之间的一个选择.要匹配 |,请使用 \| |
1.3 限定符
限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配,共6种.
| 字符 | 描述 |
|---|---|
* |
匹配前面的子表达式零次或多次.例如,zo 能匹配 "z" 以及 "zoo". 等价于{0,} |
+ |
匹配前面的子表达式一次或多次.例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z".+ 等价于 {1,} |
? |
匹配前面的子表达式零次或一次.例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" .? 等价于 {0,1} |
{n} |
n 是一个非负整数.匹配确定的 n 次.例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o |
{n,} |
n 是一个非负整数.至少匹配n 次.例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o.'o{1,}' 等价于 'o+'.'o{0,}' 则等价于 'o*' |
{n,m} |
m 和 n 均为非负整数,其中n <= m.最少匹配 n 次且最多匹配 m 次.例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o.'o{0,1}' 等价于 'o?'.请注意在逗号和两个数之间不能有空格 |
注意:
*、+限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配.- 通过在
*、+或?限定符之后放置?,该表达式从"贪心"表达式转换为"非贪心"表达式或者最小匹配.
1.4 定位符
定位符使您能够将正则表达式固定到行首或行尾.它们还使您能够创建这样的正则表达式,这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾.
定位符用来描述字符串或单词的边界,^ 和 $ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界.
| 字符 | 描述 |
|---|---|
^ |
匹配输入字符串开始的位置.如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 \n 或 \r 之后的位置匹配 |
$ |
匹配输入字符串结尾的位置.如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n 或 \r 之前的位置匹配 |
\b |
匹配一个字边界,即字与空格间的位置 |
\B |
非字边界匹配 |
注意:
- 不能将限定符与定位符一起使用.由于在紧靠换行或者字边界的前面或后面不能有一个以上位置,因此不允许诸如 ^* 之类的表达式.
- 若要匹配一行文本开始处的文本,请在正则表达式的开始使用 ^ 字符.不要将 ^ 的这种用法与中括号表达式内的用法混淆.
- 若要匹配一行文本的结束处的文本,请在正则表达式的结束处使用 $ 字符.
1.5 选择
用圆括号将所有选择项括起来,相邻的选择项之间用|分隔.但用圆括号会有一个副作用,使相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用.
其中 ?: 是非捕获元之一,还有两个非捕获元是 ?= 和 ?!,这两个还有更多的含义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串.
1.6 反向引用
对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储.缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式.每个缓冲区都可以使用 \n 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数.
可以使用非捕获元字符 ?:、?= 或 ?! 来重写捕获,忽略对相关匹配的保存.
反向引用的最简单的、最有用的应用之一,是提供查找文本中两个相同的相邻单词的匹配项的能力.
1.7 运算优先级
正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似.
相同优先级的从左到右进行运算,不同优先级的运算先高后低.下表从最高到最低说明了各种正则表达式运算符的优先级顺序:
| 运算符 | 描述 |
|---|---|
\ |
转义符 |
(),(?: ),(?=),[] |
圆括号和方括号 |
*,+,?,{n},{n,},{n,m} |
限定符 |
^,$,\何元字符、任何字符 |
定位点和序列(即: 位置和顺序) |
| | | 替换,"或"操作,字符具有高于替换运算符的优先级 |
2. 正则表达式实例
| 正则表达式 | 描述 |
|---|---|
/\b([a-z]+) \1\b/gi |
一个单词连续出现的位置 |
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ |
将一个URL解析为协议、域、端口及相对路径 |
| /^(?:Chapter | Section) [1-9][0-9]{0,1}$/ | 定位章节的位置 |
/[-a-z]/ |
a至z共26个字母再加一个-号 |
/ter\b/ |
可匹配chapter,而不能匹配terminal |
/\Bapt/ |
可匹配chapter,而不能匹配aptitude |
| /Windows(?=95|98|NT)/ | 可匹配Windows95或Windows98或WindowsNT,当找到一个匹配后,从Windows后面开始进行下一次的检索匹配 |
/^\s*$/ |
匹配空行 |
/\d{2}-\d{5}/ |
验证由两位数字、一个连字符再加 5 位数字组成的 ID 号 |
/<\s*(\S+)(\s[^>]*)?>[\s\S]*<\s*\/\1\s*>/ |
匹配 HTML 标记 |
2.1 校验数字的表达式
| 规则 | 正则表达式语法 |
|---|---|
| 数字 | ^[0-9]*$ |
| n位的数字 | ^\d{n}$ |
| 至少n位的数字 | ^\d{n,}$ |
| m-n位的数字 | ^\d{m,n}$ |
| 零和非零开头的数字 | ^(0|[1-9][0-9]*)$ |
| 非零开头的最多带两位小数的数字 | ^([1-9][0-9]*)+(\.[0-9]{1,2})?$ |
| 带1-2位小数的正数或负数 | ^(\-)?\d+(\.\d{1,2})$ |
| 正数、负数、和小数 | ^(-|+)?\d+(.\d+)?$ |
| 有两位小数的正实数 | ^[0-9]+(\.[0-9]{2})?$ |
| 有1~3位小数的正实数 | ^[0-9]+(\.[0-9]{1,3})?$ |
| 非零的正整数 | ^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$ |
| 非零的负整数 | ^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$ |
| 非负整数 | ^\d+$ 或 ^[1-9]\d*|0$ |
| 非正整数 | ^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$ |
| 非负浮点数 | ^\d+(\.\d+)?$ 或 ^[1-9]\d.\d|0.\d[1-9]\d|0?.0+|0$ |
| 非正浮点数 | ^((-\d+(.\d+)?)|(0+(.0+)?))$ 或 ^(-([1-9]\d.\d|0.\d[1-9]\d))|0?.0+|0$ |
| 正浮点数 | ^[1-9]\d.\d|0.\d[1-9]\d$ 或 ^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$ |
| 负浮点数 | ^-([1-9]\d.\d|0.\d[1-9]\d)$ 或 ^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$ |
| 浮点数 | `^(-?\d+)(.\d+)?$ 或 ^-?([1-9]\d.\d|0.\d[1-9]\d|0?.0+|0)$ |
2.2 校验字符的表达式
| 规则 | 正则表达式语法 |
|---|---|
| 汉字 | ^[\u4e00-\u9fa5]{0,}$ |
| 英文和数字 | ^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$ |
| 长度为3-20的所有字符 | ^.{3,20}$ |
| 由26个英文字母组成的字符串 | ^[A-Za-z]+$ |
| 由26个大写英文字母组成的字符串 | ^[A-Z]+$ |
| 由26个小写英文字母组成的字符串 | ^[a-z]+$ |
| 由数字和26个英文字母组成的字符串 | ^[A-Za-z0-9]+$ |
| 由数字、26个英文字母或者下划线组成的字符串 | ^\w+$ 或 ^\w{3,20}$ |
| 中文、英文、数字包括下划线 | ^[\u4E00-\u9FA5A-Za-z0-9_]+$ |
| 中文、英文、数字但不包括下划线等符号 | ^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$ |
| 可以输入含有 ^`%&',;=?$\"等字符 | ^%&',;=?$\x22]+ |
| 禁止输入含有~的字符: | ^~\x22]+ |
2.3 特殊需求表达式
| 规则 | 正则表达式语法 |
|---|---|
| Email地址 | ^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$ |
| 域名 | [a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.? |
| InternetURL | [a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ |
| 手机号码 | ^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$ |
| 电话号码 | ^((\d{3,4}-)|\d{3.4}-)?\d{7,8}$ |
| 国内电话号码(0511-4405222、021-87888822) | \d{3}-\d{8}|\d{4}-\d{7} |
| 电话号码正则表达式(支持手机号码,3-4位区号,7-8位直播号码,1-4位分机号 | ((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$) |
| 身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X: | (^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$) |
| 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线) | ^[a-zA-Z][a-zA-Z0-9_]{4,15}$ |
| 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线) | ^[a-zA-Z]\w{5,17}$ |
| 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间) | ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$ |
| 日期格式 | ^\d{4}-\d{1,2}-\d{1,2} |
| 一年的12个月(01~09和1~12) | ^(0?[1-9]|1[0-2])$ |
| 一个月的31天(01~09和1~31) | ^((0?[1-9])|((1|2)[0-9])|30|31)$ |
| xml文件 | ^([a-zA-Z]+-?)+[a-zA-Z0-9]+\.[x|X][m|M][l|L]$ |
| 中文字符的正则表达式 | [\u4e00-\u9fa5] |
| 双字节字符 | ^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)) |
| 空白行的正则表达式 | \n\s*\r (可以用来删除空白行) |
| HTML标记的正则表达式 | <(\S?)>>.?|<.? /> (首尾空白字符的正则表达式 ^\s|\s$ 或 ^\s)|(\s$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式) |
| 腾讯QQ号 | [1-9][0-9]{4,} (腾讯QQ号从10000开始) |
| 中国邮政编码 | `[1-9]\d{5}(?!\d) (中国邮政编码为6位数字) |
| IP地址 | ((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d)) |