正则表达式

658 阅读7分钟

一. 什么是正则

在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。我们使用元字符来表示某一类字符,比如数字、空格等,先介绍几个例子

eg1

如果我们要查找一个字符串中查找hi这个单词,直接使用hi匹配其实就是一个正则,只是他不精确罢了,因为带有hi这个两个字符的单词都会被匹配比如historyhim等,所以我们可以给他加一个限制\bhi\b\b这个元字符代表的意思就是我想匹配的单词到这结束,代表一个分界线,而且他并不会匹配英文中的空格,标点或者换行,他只匹配一个位置

二. 与正则相关的对象或方法

var reg = /^\w{6,12}$/

if(password.match(reg))

{alert("The password is valid!");

}

三. 常用元字符

元字符 含义
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n} 匹配n个前面表达式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。
re{ n,} 精确匹配n及以上个前面表达式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。
re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a|b 匹配a或b
\w 匹配数字字母下划线
\W 匹配非数字字母下划线
\s 匹配任意空白字符,等价于 [\t\n\r\f]。
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9]。
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z 匹配字符串结束
\G 匹配最后匹配完成的位置。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
(re) 匹配括号内的表达式,也表示一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re) 类似 (...), 但是不表示一个组
(?imx: re) 在括号中使用i, m, 或 x 可选标志
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
(?#...) 注释.
(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。
(?> re) 匹配的独立模式,省去回溯。
\n, \t, 等。 匹配一个换行符。匹配一个制表符, 等
\1...\9 匹配第n个分组的内容。
\10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

四. 部分规则解读

1. 大写与小写元字符含义相反

如上述中的\d\D前者代表匹配一个数字,后者代表匹配一个非数字

2. ?

?表示重复0次或1次

'aaaaa'用'a?'则会匹配到一个a

*?表示匹配任意次,但是尽量少匹配

如 "acbacb" 正则 "a.*?b"只会取到第一个"acb"原本可以全部取到但加了限定符后,只会匹配尽可能少的字符 ,而"acbacb"最少字符的结果就是"acb"

{n,m}? 重复n到m次,尽可能少

如 "aaaaaaaa" 正则 "a{0,m}" 因为最少是0次所以取到结果为空 综上,?表达的意思就是能使用最少字符匹配就尽量最小

3. 转义

如果匹配字符中出现了元字符,防止冲突要使用\.来将此字符转换成文本格式 例如:deerchao\.cn匹配deerchao.cn

4.字符类

使用[...]来表示需要匹配字符的一个集合,如[aeiou]代表匹配这个集合中字符,或者[0-9]代表匹配所有数字他与\d等价

例子:\(?0\d{2}[) -]?\d{8}

这个式子可以匹配(010)88886666,或022-22334455,或02912345678等号码,首先是一个转义字符\(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)或-或空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。

但是这个式子有个缺陷那就是会匹配类似010)12345678或(022-87654321的号码

5. 分枝条件

分枝条件就是或|语句,如果前者符合则取前者,否则取后者,这样上述例子可以分成两个分支

\(0\d{2}\)\d{8}

0\d{2}-\d{8}

将他们用'|'连接起来即可\(0\d{2}\)\d{8}|0\d{2}-\d{8}

分组

上述我们可以用*或者{n,m}来限定匹配重复次数,但仅限一个字符,如果要重复某个字符串组合呢,可以使用分组

例字: (\d{1,3}\.){3}\d{1,3}

这个式子代表匹配一个1-3位的数字序列加一个.,然后匹配一个1-3位的数字序列,看起来像是一个ip地址的匹配,但是却会匹配到999.999.999.999这种组合,所以我们结合上述知识写出一个标准的ip地址正则匹配式

((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

由于ip4地址范围最大是255.255.255.255所以,将255分成3个分枝,[0-199],[200-249],[250-255],加上一个.然后分成一个组,匹配3次,最后加一个组

6. 正则表达式修饰符

i 不区分(ignore)大小写;

例如: /abc/i 可以匹配 abc、aBC、Abc

g 全局(global)匹配

如果不带g,正则过程中字符串从左到右匹配,找到第一个符合条件的即匹配成功,返回

如果带g,则字符串从左到右,找到每个符合条件的都记录下来,直到字符串结尾位置

例如:

var str = 'aaaaaaaa'
var reg1 = /a/;  str.match(reg1)  // 结果为:["a", index: 0, input: "aaaaaaaa"]
var reg2 = /a/g; str.match(reg2)  // 结果为:["a", "a", "a", "a", "a", "a", "a", "a"]

m 多(more)行匹配

若存在换行\n并且有开始^或结束$符的情况下,和g一起使用实现全局匹配, 因为存在换行时默认会把换行符作为一个字符任务匹配字符串是个单行, g只匹配第一行,添加m之后实现多行,每个换行符之后就是开始

var str = "abcggab\nabcoab";
var preg1 = /^abc/gm;  str.match(preg1)  // 结果为:["abc", "abc"]
var preg2 = /ab$/gm;   str.match(preg2)  // 结果为:["ab", "ab"]

s 特殊字符圆点 . 中包含换行符

默认的圆点 . 是 匹配除换行符 \n 之外的任何单字符,加上s之后, . 中包含换行符

U 只匹配最近的一个字符串;不重复匹配;

修正符:x 将模式中的空白忽略;

修正符:A 强制从目标字符串开头匹配;

修正符:D 如果使用$限制结尾字符,则不允许结尾有换行;

修正符:e 配合函数preg_replace()使用,可以把匹配来的字符串当作正则表达式执行;

修饰符可以组合使用