Javascript正则
RegExp 对象
RegExp
对象表示正则表达式,它是对字符串执行模式匹配的强大工具。
转义:
\o | NULL字符(\u0000) |
\t | 制表符(\u0009)0) |
\n | 换行符(\u000A)0) |
\v | 垂直制表符(\u000B)0) |
\f | 换页符(\u000C)0) |
\r | 回车(\u000D)0) |
\xnn | 由十六进制数 nn 指定的拉丁字符,例如,\x0A 等价于 \n0) |
\uxxxx | 由十六进制数xxxx指定的Unicode字符,例如,\u0009等价于\t0) |
\cX | 控制字符^X。例如,\cJ等价于换行符\n0) |
^ $ . * + ? = ! : | \ / () [] {}
直接量语法
/pattern/attributes
创建RegExp
对象的语法
new RegExp(pattern, attributes);
参数
参数pattern
是一个字符串,指定了正则表达式的模式或其他正则表达式。
参数attributes
是一个可选的字符串,包含属性 g
、i
和m
,分别用于指定
「全局匹配」、「区分大小写」和「多行匹配」。ECMAScript 标准化之前,不支持m
属性。如果
pattern
是正则表达式,而不是字符串,则必须省略该参数。
返回值
一个新的RegExp
对象,具有指定的模式和标志。如果参数pattern
是正则表达式而不是
字符串,那么RegExp()
构造函数将用与指定的RegExp
相同的模式和标志创建一个新的
RegExp
对象。
如果不用new
运算符,而将RegExp()
作为函数调用,那么它的行为与用new
运算符调用
时一样,只是当pattern
是正则表达式时,它只返回 pattern
,而不再创建一个新的
RegExp
对象。
抛出
- SyntaxError
- 如果
pattern
不是合法的正则表达式,或attributes
含有g
、i
和m
之外的字符,抛出该异常。
- TypeError
- 如果
pattern
是RegExp
对象,但没有省略attributes
参数,抛出该异常。
RegExp 对象属性
FF: Firefox, IE: Internet Explorer
属性 | 描述 | FF | IE |
global | RegExp 对象是否具有标志 g。 | 1 | 4 |
ignoreCase | RegExp 对象是否具有标志 i。 | 1 | 4 |
lastIndex | 一个整数,标示开始下一次匹配的字符位置 | 1 | 4 |
multiline | RegExp 对象是否具有标志 m。 | 1 | 4 |
source | 正则表达式的源文本。 | 1 | 4 |
RegExp 对象方法
FF: Firefox, IE: Internet Explorer
方法 | 描述 | FF | IE |
compile | 编译正则表达式。 | 1 | 4 |
exec | 检索字符串中指定的值。返回找到的值,并确定其位置。 | 1 | 4 |
test | 检索字符串中指定的值。返回 true 或 false。 | 1 | 4 |
test检查指定的字符串是否存在
var data = "123123"; var reCat = /123/gi; alert(reCat.test(data)); //true
exec 返回查询值
var data = "123123,213,12312,312,3,Cat,cat,dsfsdfs,"; var reCat = /cat/i; alert(reCat.exec(data)); //Cat
支持正则表达式的String对象的方法
FF: Firefox, IE: Internet Explorer
方法 | 描述 | FF | IE |
search | 检索与正则表达式相匹配的值。 | 1 | 4 |
match | 找到一个或多个正则表达式的匹配。 | 1 | 4 |
replace | 替换与正则表达式匹配的子串。 | 1 | 4 |
split | 把字符串分割为字符串数组。 | 1 | 4 |
search 返回搜索位置
var data = "123123,213,12312,312,3,Cat,cat,dsfsdfs,"; var reCat = /cat/gi; alert(data.search(reCat)); //23
match 得到查询数组
var data = "123123,213,12312,312,3,Cat,cat,dsfsdfs,"; var reCat = /cat/gi; var arrMactches = data.match(reCat) for (var i=0;i < arrMactches.length ; i++) { alert(arrMactches[i]); //Cat cat }
replace 正则替换
var data = "123123,213,12312,312,3,Cat,cat,dsfsdfs,"; var reCat = /cat/gi; alert(data.replace(reCat,"libinqq"));
split 利用正则分割数组
var data = "123123,213,12312,312,3,Cat,cat,dsfsdfs,"; var reCat = /\,/; var arrdata = data.split(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); }
修饰符
修饰符 | 描述 |
i | 执行对大小写不敏感的匹配。 |
g | 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。 |
m | 执行多行匹配。 |
方括号
方括号用于查找某个范围内的字符:
表达式 | 描述 |
[abc] | 查找方括号之间的任何字符。 |
[^abc] | 查找任何不在方括号之间的字符。 |
[0-9] | 查找任何从 0 至 9 的数字。 |
[a-z] | 查找任何从小写 a 到小写 z 的字符。 |
[A-Z] | 查找任何从大写 A 到大写 Z 的字符。 |
[A-z] | 查找任何从大写 A 到小写 z 的字符。 |
[adgk] | 查找给定集合内的任何字符。 |
[^adgk] | 查找给定集合外的任何字符。 |
(red|blue|green) 查找任何指定的选项。
例子
匹配多个:
var data = "a,b,c,w,1,2,3,5"; //\u0062cf var reCat = /[a-q1-4\n]/gi; var arrdata = data.match(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); // a b c 1 2 3 }
匹配指定组合:
var data = "1libinqq,2libinqq,3libinqq,4libinqq"; var reCat = /[123]libinqq/gi; var arrdata = data.match(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); // 1libinqq 2libinqq 3libinqq } var data = "libinqq1,libinqq2,libinqq3,libinqq4,libinqq5"; //\u0062cf var reCat = /libinqq[2-3]/gi; var arrdata = data.match(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); // libinqq2 libinqq3 }
排除指定组合:
var data = "alibinqq,1libinqq,2libinqq,3libinqq,4libinqq"; //\u0062cf var reCat = /[^a123]libinqq/gi; var arrdata = data.match(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); //4libinqq }
元字符
元字符(Metacharacter)是拥有特殊含义的字符:
元字符 描述
. | 查找单个字符,除了换行和行结束符。 |
\w | 查找单词字符。 |
\W | 查找非单词字符。 |
\d | 查找数字。 |
\D | 查找非数字字符。 |
\s | 查找空白字符。 |
\S | 查找非空白字符。 |
\b | 匹配单词边界。 |
\B | 匹配非单词边界。 |
\0 | 查找 NUL 字符。 |
\n | 查找换行符。 |
\f | 查找换页符。 |
\r | 查找回车符。 |
\t | 查找制表符。 |
\v | 查找垂直制表符。 |
\xxx | 查找以八进制数 xxx 规定的字符。 |
\xdd | 查找以十六进制数 dd 规定的字符。 |
\uxxxx | 查找以十六进制数 xxxx 规定的 Unicode 字符。 |
量词
量词 描述
n+ | 匹配任何包含至少一个 n 的字符串。 |
n* | 匹配任何包含零个或多个 n 的字符串。 |
n? | 匹配任何包含零个或一个 n 的字符串。 |
n{X} | 匹配包含 X 个 n 的序列的字符串。 |
n{X,Y} | 匹配包含 X 或 Y 个 n 的序列的字符串。 |
n{X,} | 匹配包含至少 X 个 n 的序列的字符串。 |
n$ | 匹配任何结尾为 n 的字符串。 |
^n | 匹配任何开头为 n 的字符串。 |
?=n | 匹配任何其后紧接指定字符串 n 的字符串。 |
?!n | 匹配任何其后没有紧接指定字符串 n 的字符串。 |
简单分组
举例 我们要查找字符串MouseMouse
:
var reCat = /MouseMouse/gi;
尽管这是可以的,但是有点浪费。如果不知道Mouse
在字符串中到底出现几次时该怎么办
,如果重复多次呢?
var data = "Ah-mousemouse"; var reCat = /(mouse){2}/gi; var arrdata = data.match(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); }
非捕获性分组
如果要创建一个非捕获性分组,只要在左括号的后面加上一个问号和一个紧跟的冒号:
var sToMatch = "#123456789"; var reNumbers = /#(?:\d+)/; reNumbers.test(sToMatch); alert(RegExp.$1);
这个例子的最后一行代码输出一个空字符串,因为该组是非捕获性的,
var sToMatch = "#123456789"; var reNumbers = /#(?:\d+)/; alert(sToMatch.replace(reNumbers,"abcd$1"));
正因如此,replace()
方法就不能通过RegExp.$x
变量来使用任何反向引用。
这段代码输出的abcd$1
而不是abcd123456789
,
因为$1
在这里并不被看成是一个反向引用。
复杂分组
?
零次 或 一次;*
零次 或 多次;+
最少一次 或 多次。
var data = "bb ba da bad dad aa "; var reCat = /([bd]ad?)/gi; // 匹配出 ba da bad dad var arrdata = data.match(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); }
同时,也不介意将分组放在分组中间:
var re = /(mom( and dad)?)/; 匹配出 mom 或 mon and daa
反向引用
var sToMatch = "#123456789"; var reNumbers = /#(\d+)/; reNumbers.test(sToMatch); alert(RegExp.$1);
这个例子尝试匹配后面跟着几个或多个数字的镑符合,并对数字进行分组以存储他们。
在调用test
方法后,所有的反向引用都保存到了RegExp
构造函数中从RegExp.$1
(它保存了第一个反向引用)开始,
如果还有第二个反向引用,就是RegExp.$2
,
如果还有第三个反向引用存在,就是RegExp.$3
.依此类推。
因为该组匹配了 「123456780」,所以RegExp.$1
中就存储了这个字符串。
var sToChange = "1234 5678"; var reMatch = /(\d{4}) (\d{4})/; var sNew = sToChange.replace(reMatch,"$2 $1"); alert(sNew);
在这个例子中,正则表达式有两个分组,每一个分组有四个数字。
在replace()
方法的第二个参数中,$2
等同于 「5678」 ,
而$1
等同于 「1234」,对应于它们在表达式中的出现顺序。
候选
var sToMatch1 = "red"; var sToMatch2 = "black"; var reRed = /red/; var reBlack = /black/; alert(reRed.test(sToMatch1) || reBlack.test(sToMatch1)); alert(reRed.test(sToMatch2) || reBlack.test(sToMatch2));
这虽然能完成任务,但是十分沉长,还有另一种方式就是正则表达式的候选操作符。
var sToMatch1 = "red"; var sToMatch2 = "black"; var reRedOrBlack = /(red|black)/; alert(reRedOrBlack.test(sToMatch1)); alert(reRedOrBlack.test(sToMatch2));
前瞻
前瞻 就和它名字一样,它告诉正则表达式运算器向前看一些字符而不是移动位置:
var sToMatch1 = "bedroom"; var sToMatch2 = "bedding"; var reBed = /bed(?=room)/; alert(reBed.test(sToMatch1)); //true alert(reBed.test(sToMatch2)); //false
负向前瞻
var sToMatch1 = "bedroom"; var sToMatch2 = "bedding"; var reBed = /bed(?!room)/; alert(reBed.test(sToMatch1)); //false alert(reBed.test(sToMatch2)); //true
边界
/* ^ 行开头 $ 行结尾 \b 单词的边界 \B 非单词的边界 */ var sToMatch = "Important word is the last one."; var reLastWord = /(\w+)\.$/; reLastWord.test(sToMatch); alert(RegExp.$1); //one
假如想查找一个单词,但要它只出现在行尾,则可以使用美元符号来表示它:
var sToMatch = "Important word is the last one."; var reLastWord = /^(\w+)/; reLastWord.test(sToMatch); alert(RegExp.$1); //Important
在这个例子中,正则表达式查找行起始位置后的一个或多个单词字符。如果遇到非单词字符
匹配停止,返回Important
。 这个例子也可以用单词边界实现:
var sToMatch = "Important word is the last one."; var reLastWord = /^(.+?)\b/; reLastWord.test(sToMatch); alert(RegExp.$1); //Important
这里,正则表达式用惰性量词来制定在单词边界之前可以出现任何字符,且可以出现一次或 多次(如果使用贪婪性量词,表达式就匹配整个字符串)。
var data = " First second thind fourth fifth sixth "; var reCat = /\b(\S+?)\b/g; var arrdata = data.match(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); }
使用单词边界可以方便地从字符串中抽取单词。
多行模式
要制定多行模式,只要在正则表达式想要匹配的行末的一个单词
var data = " First second\n thind fourth\n fifth sixth"; var reCat = /(\w+)$/g; var arrdata = data.match(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); }
上面只返回一个单词sixth
,因为换行符阻挡了匹配,只能匹配行末的一个单词, 当然也
可以使用split()
方法将字符串分割成数组,但就得对每一行进行单独匹配。
以前不好好看书经常半吊子,看一半就仍了,导致用了好多split
, 其实很简单如下面例
子只需要m
参数进行多行匹配:
var data = " First second\n thind fourth\n fifth sixth"; var reCat = /(\w+)$/gm; var arrdata = data.match(reCat); for (var i = 0; i < arrdata.length; i++) { alert(arrdata[i]); }
常用例子
中文字
验证:
function checkName(username) { return /^[\u4e00-\u9fa5a-z][\u4e00-\u9fa5a-z0-9 ]+$/i.test(username); };
提取:
username.match(/^([\u4e00-\u9fa5])+$/i)
手机号
function testMobile(phoneno) { return /^1[3|4|5|8][0-9]\d{8}$/.test(phoneno); }