简介
正则表达式,又称正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。
说人话就是:对字符串执行模式匹配的强大工具。
Javascript中的正则表达式相较于其他语言来说实现的并不完整,但仍然是十分强大的,能够帮助我们完成绝大多数模式匹配任务。
定义
在javascript中,正则表达式的定义和数组以及对象的定义一样有俩种方式。 一种是直接量,另一种是构造函数。
直接量
Javascript可以使用类似Perl的语法定义一个正则表达式
var r = /pattern/flags;
其中pattern是任何简单或复杂的正则表达式,flags是用以表达正则表达式行为的一个或者多个标识。
flags
g 表示全局(global)模式,即模式将被应用于所有字符串
i 表示不区分大小写
m 多行模式
举个栗子:
var reg1 = /ip/g; // 匹配字符串中所有'ip'的实例 var reg2 = /com/gi; // 匹配以'com'结尾的三个字符的组合,不区分大小写
使用构造函数
Javascript中正则表达式的构造函数为RegExp,即Regular Expression的缩写,它接收两个参数,第一个为要匹配的字符串模式,另一个是可选的标识位。
var reg = new RegExp('nice','g'); // 匹配字符串中所有的'nice'
注意:第一个参数是一个字符串nice
,而不是正则表达式的直接量/nice/
。
双重转义
所有元字符都需要进行双重转义
所有元字符都需要进行双重转义
所有元字符都需要进行双重转义
使用构造函数
定义正则表达式,由于构造函数的第一个参数必须是一个字符串,在匹配元字符时,需要双重转义。
// 匹配{user} var reg1 = new RegExp('\{user\}','g'); // wrong // 由于\在字符串中需要转义为\\,所以,如果要匹配{user},正则表达式需要写为 var reg1 = new RegExp('\\{user\\}','g');
基本概念总结
元字符
在正则表达式的模式中,有一些字符是有特殊含义的,被称为元字符,如果要匹配元字符,则必须对其进行转义,如果用构造函数,则要进行双重转义。
这些元字符分别是(一共14个):
{ ( [ \ ^ $ | ? * + . ] ) }
直接量字符
| 字符 | 匹配 |
| ------------- |:-------------:|
|字母数字字符|自身|
|\0 |查找 NUL 字符。|
|\n |查找换行符。|
|\f |查找换页符。|
|\r |查找回车符。|
|\t |查找制表符。|
|\v |查找垂直制表符。|
|\xxx |查找以八进制数 xxx 规定的字符。|
|\xdd |查找以十六进制数 dd 规定的字符。|
|\uxxxx |查找以十六进制数 xxxx 规定的 Unicode 字符。|
不管一个直接量字符字符代表何种含义,单个字符始终只匹配单个字符
字符类
| 字符 |等价于| 匹配 |
| ------------- |:-------------:| :-------------:|
| . | 1|查找单个字符,除了换行和行结束符。 |
| \w| [a-zA-Z_0-9]|任意ASCII单字字符,等价于[a-zA-Z0-9_]|
| \W| 2 |查找非单词字符。 |
|\d |[0-9]|查找数字。|
|\D |3|查找非数字字符。|
|\s |[ \t\n\x0B\f\r]|查找空白字符。|
|\S |4|查找非空白字符。|
|[]||来表示单个字符有或的关系,如/[bc]/,匹配b或者c|
|^||来表示不匹配后面跟着的字符,如/5,/不匹配b或c|
|-||来表示一个范围,如/[a-z]/,匹配a-z的字母,可以和负向类结合/^0-9/|
|组合类:||以上几种类组合而成的字符类,如/a-z0-9\n/,匹配a-z的字母或者0-9的数字或者换行符|
注意:在javascript类不能嵌套,就是不支持联合类和交叉类,/a-m[p-z]/和/a-m6/在JavaScript中是非法的
锚字符
| 字符 | 含义|
| ------------- |:-------------:|
| ^ | 匹配字符串的开头,在多行检索中,匹配一行的开头|
| $| 匹配字符串的结尾,在多行检索中,匹配一行的结尾|
|\b |匹配单词边界。|
|\B |匹配非单词边界。|
量词
简单量词
| 常用量词 | {m,n}等价形式|描述 |
| ------------- |:-------------:| :-------------:|
|?|{0,1}|最多出现1次,例如,do(es)? 匹配 do 或 does 中的 do|
|* |{0,}|可能出现,也可能不出现,出现次数无上限,例如,zo* 匹配 z 和 zoo。|
|+ |{1,}|最少出现1次,例如,zo+ 匹配 zo 和 zoo,但不匹配 z|
在正则表达式概念中,称 +、*、?为常用量词,称{n,m}形式的为通用量词。
使用情景举例
**?的使用
**
情景:美式应用和英式语言的单词写法不同,比如traveler和traveller.
var str1 = 'traveler'; var str2 = 'traveller'; var pattern = /travell?er/; console.log(pattern.test(str1)); console.log(str2.search(str2)); 结果打印: true 0
匹配各类标签(前端应用)
复杂量词
贪婪量词:先匹配整个字符串,如果不匹配则去掉最后一个字符再匹配,直到没有任何字符。它是从后向前匹配。
所有简单量词都是贪婪的
。惰性量词:和贪婪量词相反,即先匹配第一个字符,不匹配则匹配第一第二个字符,直到最后整个字符串。
所有简单量词后面加?就是惰性的了
。支配量词:只匹配整个字符串一次,不匹配就结束,也称最懒量词,
所有简单量词后面加+就是支配的了,但是javascript不支持,所以它连出场的机会也没有了。
。
举个栗子(complex-quantifiers.js):
var re1 = /.*bbb/g; // 定义贪婪量词 var re2 = /.*?bbb/g; // 定义简单惰性 // var re3 = /.*+bbb/g;//支配性,javascript不支持,nodejs报错 var str='abbbaabbbaaabbb1234'; console.log(re1.test(str)); //true console.log(re1.exec(str)); //null console.log(str.match(re1)); //abbbaabbbaaabbbb console.log(re2.test(str)); //true console.log(re2.exec(str)); //aabbb console.log(str.match(re2)); //abbb,aabbb,aaabbb
分组
到目前为止,我们只能一个字符到匹配,虽然量词的出现,能帮助我们处理一排密紧密相连的同类型字符。但这是不够的,下面该轮到小括号出场了,中括号表示范围内选择,大括号表示重复次数。小括号允许我们重复多个字符。
举个栗子(group.js):
//分组+量词 console.log(/(dog){2}/.test("dogdog"))//true //分组+范围 console.log("baddad".match(/([bd]ad?)*/))//baddad,dad //分组+分组 console.log("mon and dad".match(/(mon( and dad)?)/))//mon and dad,mon and dad,and dad
优先级
|优先级| 符号|说明|
| ------------- |:-------------:| :-------------:|
|最高 |\|转义符|
|高 |( )、(?: )、(?= )、[ ]|单元和字符类|
|中 |*、+、?、{n}、{n,}、{m,n}|量词|
|低 |^、$、\任何元字符、任何字符|描点|
|最低|\||替换,选择|
参考加减乘除,先算括号内的记忆方式
RegExp对象
RegExp属性
global 属性 | ignoreCase 属性 | multiline 属性 | source 属性
global: 返回布尔值,该值指示使用正则表达式的 global 标志 (g) 的状态。 默认值为 false。
只读。
ignoreCase: 返回布尔值,该值指示在正则表达式中使用的 ignoreCase 标志 (i) 的状态。 默认值为 false。
只读。
multiline: 返回布尔值,该值指示在正则表达式中使用的 multiline 标志 (m) 的状态。 默认值为 false。
只读。
source: 返回正则表达式模式的文本的一个副本。 只读。
lastIndex: 如果使用了全局模式,这个变量保存的是字符串中尝试下次匹配的偏移值。在exec和test中都会用到这个变量。
可写
RegExp方法
RegExp 对象有 3 个方法:test()、exec() 以及 compile()
RegExp.test(string)
test 方法检查字符串中是否存在某种模式,如果存在,则返回 true,否则返回 false。test 方法不修改全局 RegExp 对象的属性。
语法:
rgExp.test(str) // 参数 rgExp 必需。 包含正则表达式模式和适用标志的 Regular Expression 对象的实例。 str 必需。 将对其执行搜索的字符串。
栗子:
var str = 'huangge is an handsome man'; var reg1 = new RegExp( 'handsome','g' ); var result = reg1.test(str); console.log('huangge is an handsome man: ' + result);
RegExp.exec(string)
exec 方法使用正则表达式模式对字符串执行需找匹配,如果成功,则返回表示匹配信息的数组,否则返回null。默认情况下,它返回第一次匹配的结果
语法:
rgExp.exec(str) // 参数 rgExp 必需。 包含正则表达式模式和适用标志的 Regular Expression 对象的实例。 str 必需。 对其执行搜索的 String 对象或字符串文本。
返回值
如果成功匹配,exec 方法返回一个数组,并且更新正则表达式对象的属性。返回的数组包括匹配的字符串作为第一个元素,紧接着一个元素对应一个成功匹配被捕获的字符串的捕获括号(capturing parenthesis)。
如果匹配失败,exec 方法将返回 null。
栗子(regexp-exec.js):
var reg= /\d{4}-\d{2}-\d{2}/g; var str = 'aaa2015-08-11aaaaaabbss2015-08-22bbb'; var result = reg.exec(str); console.log(result); 结果如下: [ '2015-08-11',index: 3,input: 'aaa2015-08-11aaaaaabbss2015-08-22bbb' ]
RegExp.compile(string)
将正则表达式编译为内部格式,从而更快地执行。
语法:
rgExp.compile(pattern,[flags]) // 参数 rgExp 必需。 Regular Expression 对象的一个实例。 可以是变量名或文本。 pattern 必需。 一个字符串表达式,包含要编译的正则表达式模式 flags 可选。 可以组合使用的可用标志有: g(全局搜索出现的所有模式) i(忽略大小写) m(多行搜索)
compile 方法将 pattern 转换为内部的格式,从而执行得更快。 例如,这允许在循环中更有效地使用正则表达式。 当重复使用相同的表达式时,编译过的正则表达式使执行加速。 然而,如果正则表达式发生更改,则这种编译毫无益处。
String的正则方法
String.match(RegExp)
这个方法类似RegExp.exec(string),只是调换了RegExp和string的位置。 另一个区别就是,无论是否指定全局,RegExp.exec(string)只是返回单词匹配结果。 而string.match()会返回一个字符串数组,其中包含了各次匹配成功的文本
举个栗子(string-match.js):
var reg= /\d{4}-\d{2}-\d{2}/g; var str = 'aaa2015-08-11aaaaaabbss2015-08-22bbb'; var result = str.match(reg); console.log(result); 打印的结果为: [ '2015-08-11','2015-08-22' ]
String.search(RegEexp)
这个用来寻找某个正则表达式在字符串第一次匹配成功的位置,如果不成功,则返回-1
举个栗子(string-search.js):
var str1 = 'sssssaa111'; var str2 = 'sssssaaaaa'; var pattern = /\d/; console.log ('st1 ' + str1.search(pattern)); console.log ('st2 ' + str2.search(pattern)); 打印的结果为: st1 7 st2 -1
String.replace(RegExp,replacement)
这个方法用来正则表达式替换。 将匹配到的文本替换为replacement。默认情况替换一次。如果设定了全局模式,则所有能匹配的文本都会替换。
举个栗子(string-replace.js):
var reg = /\d{4}-\d{2}-\d{2}/; var str = '2015-08-11 2015-08-22'; console.log(str.replace(reg,'Date:')); 打印的结果为: ate: 2015-08-22
String.split(RegExp [,limit])
这个方法使用一个正则表达式切分字符串,正则表达式是否使用全局对结果没有影响
举个栗子(string-split.js):
var str = 'one two three four'; var pattern = /\s+/; console.log(str.split(pattern)) 打印的结果为: [ 'one','two','three','four' ]
常用的正则表达式
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
匹配空白行的正则表达式:\n\s*\r
匹配首尾空白字符的正则表达式:^\s|\s$
匹配Email地址的正则表达式:\w+([-+.]\w+)@\w+([-.]\w+)\.\w+([-.]\w+)*
匹配网址URL的正则表达式:[a-zA-z]+://@L_403_14@*
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^a-zA-Z{4,15}$
匹配国内电话号码:\d{3}-\d{8}|\d{4}-\d{7}
匹配腾讯QQ号:1-9{4,}
匹配中国邮政编码:[1-9]\d{5}(?!\d)
匹配身份证:\d{15}|\d{18}
匹配ip地址:\d+\.\d+\.\d+\.\d+
匹配特定数字
^[1-9]\d*$ //匹配正整数 ^-[1-9]\d*$ //匹配负整数 ^-?[1-9]\d*$ //匹配整数 ^[1-9]\d*|0$ //匹配非负整数(正整数 + 0) ^-[1-9]\d*|0$ //匹配非正整数(负整数 + 0) ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ //匹配正浮点数 ^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ //匹配负浮点数 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$ //匹配浮点数 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ //匹配非负浮点数(正浮点数 + 0) ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ //匹配非正浮点数(负浮点数 + 0)
匹配特定字符串
^[A-Za-z]+$ //匹配由26个英文字母组成的字符串 ^[A-Z]+$ //匹配由26个英文字母的大写组成的字符串 ^[a-z]+$ //匹配由26个英文字母的小写组成的字符串 ^[A-Za-z0-9]+$ //匹配由数字和26个英文字母组成的字符串 ^\w+$ //匹配由数字、26个英文字母或者下划线组成的字符串