(1)JavaScript通过内置对象RegExp支持正则表达式,两种方法实例化RegExp对象
字面量和构造函数
//字面量方式:
var reg = /\bis\b/
var text = 'He is a boy.'
var result = text.replace(reg, 'IS') // 'He IS a boy.'
//构造函数
var reg = new RegExp('\\bis\\b', 'g')//注意这个写法, new RegExp('\bis\b', 'g')这样写会报错
var text = 'He is a boy. It is a dog'
var result = text.replace(reg, 'IS') // 'He IS a boy. It IS a dog'
注:正如不推荐使用new Array而是使用[]创建数组一样,推荐使用字面量创建RegExp对象实例。
(2)修饰符:
g:global 全文搜索
i:ignore case 忽略大小写
m:multiple lines 多行搜索
(3)元字符和字符类
元字符:元字符是在正则表达式中有特殊含义的非字母字符,如\b代表单词边界,可以是单词的开头或结尾。
字符类:很多时候,我们不想匹配某个字符,而想匹配某类字符。此时,我们可以使用元字符[]来构建一个简单的类。
字符类包括简单类,反向类,范围类,组合类,预定义类
//简单类
var re = /[abc123]/;//将匹配abc123这6个字符中一个
//负向类
re = /[^abc]/;//将匹配除abc之外的一个字符
//范围类
re = /[a-b]/;//将匹配小写a-b 26个字母
re = /[^0-9]/;//将匹配除0-9 10个字符之处的一个字符
//组合类
re = /[a-b0-9A-Z_]/;//将匹配字母,数字和下划线
(4)预定义类和边界
(5)量词(下表量词单个出现时皆是贪婪量词)
(6)贪婪量词与惰性量词
•用贪婪量词进行匹配时,它首先会将整会字符串当成一个匹配,如果匹配的话就退出,如果不匹配,就截去最后一个字符进行匹配,如果不匹配,继续将最后一个字符截去进行匹配,直到有匹配为止。直到现在我们遇到的量词都是贪婪量词
•用惰性量词进行匹配时,它首先将第一个字符当成一个匹配,如果成功则退出,如果失败,则测试前两个字符,依些增加,直到遇到合适的匹配为止
惰性量词仅仅在贪婪量词后面加个"?"而已,如"a+"是贪婪匹配的,"a+?"则是惰性的
var str = "abc";
var re = /\w+/;//将匹配abc
re = /\w+?/;//将匹配a
(7)分组与非捕获性分组 (也叫忽略分组)
有时候会想要匹配一串字符串连续出现多次的情况,使用()
可以达到分组的功能
这样写Byron{3},只会匹配Byronnn,这样写(Byron){3}才能匹配ByronByronByron
当不希望捕获某些分组,只需要在分组内加上?:,也就是这么(
?:Byron)写。
(8)反向引用
当包含分组的正则表达式进行过test,match,search这些方法之后,每个分组都被放在一个特殊的地方以备将来使用,这些存储是分组中的特殊值,我们称之为反向引用
let text = '2018-07-09'
let reg = /(\d{4})-(\d{2})-(\d{2})/g
/*
$1是(\d{4})的匹配内容,代表yyyy
$2是第一个(\d{2})的匹配内容,代表MM
$3是第二个(\d{2})的匹配匹配内容,代表DD
*/
text=text.replace(reg, '$2/$3/$1') // 07/09/2018
(9)RegExp对象属性
常用对象属性主要有以下几种:
1.global: 是否全文搜索,默认false
2.ignore case:是否大小写敏感,默认是false
3.multiline:多行搜索,默认值是false
4.lastIndex:是当前表达式匹配内容的最后一个字符的后一位,用于规定下一次匹配的起始位置,lastIndex 属性被 RegExp 对象的 exec 和 test 方法修改.并且它是可写的.
var re = /[A-Z]/;
//exec方法执行后,修改了re的lastIndex属性,
var str = "Hello,World!!!";
var arr = re.exec(str);
alert(re.lastIndex);//0,因为没有设置全局标志
re = /[A-Z]/g;
arr = re.exec(str);
alert(re.lastIndex);//1
arr = re.exec(str);
alert(re.lastIndex);//7
注意:当匹配失败(后面没有匹配),或lastIndex值大于字符串长度时,再执行exec等方法会将lastIndex设为0(开始位置)
5.source:正则表达式的文本字符串
(10)字符串对象方法
1.search方法
String.prototype.search(reg)
search方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,方法返回第一个匹配结果的index,查找不到则返回-1
。
说明:
search方法不执行全局匹配,它将忽略标志g,并且总是从字符串的开始进行检索,因此,它不会产生类似于test方法的问题;
不输入正则表达式则search方法将会自动将其转为正则表达式
2.match方法
String.prototype.match(reg)
match方法将检索字符串,以找到一个或多个与reg匹配的文本,reg是否具有标志g
对结果影响很大。
说明:
非全局调用
如果reg没有标识g
,那么match方法就只能在字符串中执行一次匹配,如果没有找到任何匹配的文本,将返回null
,否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。
返回数组的第一个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式匹配的文本。
除了常规的数组元素之外,返回的数组还含有2个对象属性:
- index:声明匹配文本的起始字符在字符串的位置
- input:声明对stringObject的引用
let reg = /\d(\w)\d/ let text = '$1a2b3c4e5e' // 子表达式是 /\w/,匹配a let result = text.match(reg) // ["1a2", "a"] result.index // 1 // 不管lastIndex result.lastIndex // 0 result.input // '$1a2b3c4e5e'
全局调用
如果regexp具有标志
g
则match方法将执行全局检索,找到字符串中的所有匹配子字符串。如果没有找到任何匹配的子串,否则,返回一个数组。数组元素中存放的是字符串中所有的匹配子串,而且也没有index属性或input属性。
let reg = /\d(\w)\d/g let text = '$1a2b3c4e5e' let result = text.match(reg) // ["1a2", "3c4"] result.index // undefined result.input // undefined result.lastIndex // 0
3.split方法
String.prototype.split(reg)
我们经常使用split方法将字符串分割为字符数组:
'a, b, c, d'.split(',') // ["a", "b", "c", "d"]
在一些复杂的分割情况下我们可以使用正则表达式解决:
'a, b, c, d'.split(/,/) // ["a", "b", "c", "d"]
'a1b2c3d'.split(/\d/) // ["a", "b", "c", "d"]
4.
replace方法
replace方法有三种形态:
String.prototype.replace(str, replaceStr)
String.prototype.replace(reg, replaceStr)
'a1b1c1'.replace('1', 2) // 'a2b1c1'
'a1b1c1'.replace(/1/g, 2) // 'a2b2c2'
String.prototype.replace(reg, function)
function会在每次匹配替换的时候调用,有四个参数
1.匹配字符串
2.正则表达式分组内容,没有分组则没有该参数
3.匹配项在字符串中的index
4.原字符串
'a1b2c3d4e5'.replace(/\d/g, (match, index, origin) => {
console.log(index)
return parseInt(match) + 1
})
// 1 3 5 7 9
// 'a2b3c4d5e6'
'a1b2c3d4e5'.replace(/(\d)(\w)(\d)/g, (match, group1, group2, group3, index, origin) => {
console.log(match)
return group1 + group3
})
// '1b2' '3d4'
// ''a12c34e5 => 去除了第二个分组\w匹配到的b和d
(11)正向前瞻(先行断言)和负向前瞻(先行否定断言)
正向前瞻:只有当字符后面跟着某个特定字符才去捕获它 ?=
负向前瞻:只有当字符后面不跟着某个特定字符时才去匹配它 ?!
注意:执行前瞻和负向前瞻之类的运算时,正则表达式引擎会留意字符串后面的部分,然而却不移动index
//正向前瞻
re = /([a-z]+(?=\d))/i;
//我们要匹配后面跟一个数字的单词,然后将单词返回,而不要返回数字
str = "abc every1 abc";
alert(re.test(str));//true
alert(RegExp.$1);//every
alert(re.lastIndex);//使用前瞻的好处是,前瞻的内容(?=\d)并不会当成一次匹配,下次匹配仍从它开始
//负向前瞻(?!)
re = /([a-z](?!\d))/;i
//将匹配后面不包含数字的字母,并且不会返回(?!\d)中的内容
str = "abc1 one";
alert(re.test(str));
alert(RegExp.$1);//one