正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。
搜索模式可用于文本搜索和文本替换。
目录
RegExp.prototype.exec() 可用来匹配字符串中符合正则表达式的字符串
如果匹配到,返回值是一个result数组:[匹配的内容,index: 在str中匹配的起始位置,input: 参数字符串,groups: undefined],否则返回null。
RegExp.prototype.test() 用来测试待检测的字符串中是否有可以匹配到正则表达式的字符串,如果有返回true,否则返回false。
toString()/toLocaleString() 把正则表达式的内容转化成字面量形式字符串/有本地特色的字符串(JS中没效果)
ignoreCase、global、multiline 判断正则表达式中是否有忽略大小写、全局匹配、多行匹配三个模式修饰符
source 返回字面量形式的正则表达式(类似于toString)
什么是正则表达式?
正则表达式是由一个字符序列形成的搜索模式。
当你在文本中搜索数据时,你可以用搜索模式来描述你要查询的内容。
正则表达式可以是一个简单的字符,或一个更复杂的模式。
正则表达式可用于所有文本搜索和文本替换的操作。
正则表达式的创建方法
1.直接使用字面量
格式:var reg = /正则表达式/修饰符
var reg1 = /hello/igm;
2.使用构造函数
格式:var reg = new RegExp('正则表达式','修饰符')
var reg2 = new RegExp('hello','igm');
字符分类
普通字符
字母、数字、下划线、汉字、没有特殊含义的符号(,;!@等)
实际上不是特殊字符的字符都是普通字符
特殊字符
\:将特殊字符转义成普通字符
模式修饰符
i:ignoreCase,匹配时忽视大小写
m:multiline,多行匹配
g:global,全局匹配
字面量创建正则时,模式修饰符写在一对反斜线后
正则表达式实例方法
RegExp.prototype.exec() 可用来匹配字符串中符合正则表达式的字符串
如果匹配到,返回值是一个result数组:[匹配的内容,index: 在str中匹配的起始位置,input: 参数字符串,groups: undefined],否则返回null。
var reg1 = /hello/igm;
var str = 'hello world hello java hello javascript';
console.log(reg1.exec(str));
注意点:
1.如果正则表达式中有修饰符"g",这时,在正则表达式的实例reg中会维护lastIndex属性,记录下一次开始的位置,当第二次执行exec的时候,从lastIndex开始检索。
2.如果正则表达式中没有修饰符"g",不会维护lastIndex属性,每次执行从开始位置检索。
RegExp.prototype.test() 用来测试待检测的字符串中是否有可以匹配到正则表达式的字符串,如果有返回true,否则返回false。
var reg2 = new RegExp('hello','igm');
var str = 'hello world hello java hello javascript';
console.log(reg2.test(str));
注意点:
1.如果正则表达式中有修饰符"g",这时,在reg中会维护lastIndex属性,记录下一次开始的位置,当第二次执行test的时候,从lastIndex开始检索。
2.如果正则表达式中没有修饰符"g",不会维护lastIndex属性,每次执行从开始位置检索。
toString()/toLocaleString() 把正则表达式的内容转化成字面量形式字符串/有本地特色的字符串(JS中没效果)
var reg1 = /hello/igm;
var str = 'hello world hello java hello javascript';
console.log(reg1.toString(str));
console.log(reg1.toLocaleString(str));
valueOf() 返回正则表达式本身
var reg1 = /hello/igm;
var str = 'hello world hello java hello javascript';
console.log(reg1.valueOf(str));
正则表达式实例属性
lastIndex
当没设置全局匹配时,该属性值始终为0。
设置了全局匹配时,每执行一次exec/test来匹配,lastIndex就会移向匹配到的字符串的下一个位置,当指向的位置后没有可以再次匹配的字符串时,下一次执行exec返回null,test执行返回false,然后lastIndex归零,从字符串的开头重新匹配一轮,可以理解成,每次正则查找的起点就是lastIndex。
var reg1 = /hello/igm;
var str = 'hello world hello java hello javascript';
console.log(reg1.lastIndex);
console.log(reg1.test(str));
console.log(reg1.lastIndex);
console.log(reg1.test(str));
console.log(reg1.lastIndex);
console.log(reg1.test(str));
console.log(reg1.lastIndex);
console.log(reg1.test(str));
console.log(reg1.lastIndex);
ignoreCase、global、multiline 判断正则表达式中是否有忽略大小写、全局匹配、多行匹配三个模式修饰符
var reg1 = /hello/igm;
var str = 'hello world hello java hello javascript';
console.log(reg1.ignoreCase);
console.log(reg1.global);
console.log(reg1.multiline);
source 返回字面量形式的正则表达式(类似于toString)
var reg1 = /hello/igm;
var str = 'hello world hello java hello javascript';
console.log(reg1.source);
正则表达式语法-元字符
直接量字符
// 直接量字符
var reg = /\n/;
console.log(reg.test('hello \n world'));
console.log('hello \n world');
字符集合
一个字符集合,也叫字符组。匹配集合中的任意一个字符。你可以使用连字符‘-’指定一个范围。
注意:^写在[]里面是反义字符组
// 字符集合
var reg1 = /[abc]/; //匹配任意在方括号内的字符
var reg2 = /[0-9]/; //查找任何从0到9的数字
var reg3 = /[^xyz]/; //匹配任意不在括号内的字符
var str = 'aaa hello world';
console.log(reg1.test(str));
console.log(reg2.test(str));
console.log(reg3.test(str));
边界符
^ 匹配输入开始。表示匹配行首的文本(以谁开始)。如果多行(multiline)标志被设为 true,该字符也会匹配一个断行(line break)符后的开始处。
$ 匹配输入结尾。表示匹配行尾的文本(以谁结束)。如果多行(multiline)标志被设为 true,该字符也会匹配一个断行(line break)符的前的结尾处。
如果 ^和 $ 在一起,表示必须是精确匹配。
// 边界符
var reg1 = /^abc/;
var reg2 = /def$/;
console.log(reg1.test('abcdef'));
console.log(reg1.test('aabcdef'));
console.log(reg1.test('abdcdefg'));
console.log(reg2.test('abcdef'));
console.log(reg2.test('aabcdef'));
console.log(reg2.test('abdcdefg'));
// 精准匹配
var reg3 = /^abc$/;
console.log(reg3.test('abc'));
console.log(reg3.test('abcabc'));
字符集合与"^"和"$"一起使用
// 边界符和字符集合一起使用
var reg = /^[abc]/; //三选一 只有开头是a 或者是b 或者是c 这三个字母才返回 true
console.log(reg.test('aqwe'));
console.log(reg.test('bqwe'));
console.log(reg.test('dqwe'));
var reg = /[def]$/; //三选一 只有结尾是d 或者是e 或者是f 这三个字母才返回 true
console.log(reg.test('aqwe'));
console.log(reg.test('bqwf'));
console.log(reg.test('dqwg'));
var reg = /^[abc]$/; // 三选一 只有是a 或者是b 或者是c 这三个字母才返回 true
console.log(reg.test('a'));
console.log(reg.test('b'));
console.log(reg.test('ab'));
console.log(reg.test('abc'));
console.log(reg.test('abce'));
零宽/非零宽单词边界 \b \B
\b 匹配一个零宽单词边界(zero-width word boundary),表示一个单词(而非字符)边界,也就是单词和空格之间的位置,或者字符(\w)与字符串开头或者结尾之间的位置。
\B 匹配一个零宽非单词边界(zero-width non-word boundary),与"\b"相反。
// 零宽 \b 和非零宽 \B 单词
var reg = /\bworld\b/;
var str = 'Hello world javascript';
console.log(reg.exec(str));
var reg = /\Borl\B/;
var str = 'Hello world javascript';
console.log(reg.exec(str));
字符类
// 字符类
// \. [^\n\r]
var reg = /\./;
console.log('hello\nworld');
console.log(reg.test('hello\nworld'));
// \d [0-9] \D [^0-9]
var reg = /\d/;
var reg = /\D/;
console.log(reg.test('123'));
console.log(reg.test('123a'));
console.log(reg.test('a'));
// \w [A-Za-z0-9_] \W [^A-Za-z0-9_]
var reg = /\w/;
var reg = /\W/;
console.log(reg.test('123'));
console.log(reg.test('123a'));
console.log(reg.test('a'));
console.log(reg.test('!'));
console.log(reg.test(' '));
// \s [\t\r\n\f] \S [^\t\r\n\f]
var reg = /\s/;
var reg = /\S/;
console.log(reg.test('!'));
console.log(reg.test(' '));
console.log(reg.test('\n'));
console.log(reg.test('a'));
console.log(reg.test('1'));
数量词
// 数量词 * + ? {n} {n,} {m,n}
// 1.*匹配字符>=0次
var reg = /^a*$/;
console.log(reg.test(''));
console.log(reg.test('a'));
console.log(reg.test('aa'));
// 2.+匹配字符>=1次
var reg = /^b+$/;
console.log(reg.test(''));
console.log(reg.test('b'));
console.log(reg.test('bb'));
// 3.?匹配字符0次 1次
var reg = /^c?$/; //加精准匹配
console.log(reg.test(''));
console.log(reg.test('c'));
console.log(reg.test('cc'));
console.log(reg.test('ccc'));
// 4.{n}匹配字符 n次
var reg = /^d{3}$/;
console.log(reg.test(''));
console.log(reg.test('d'));
console.log(reg.test('dd'));
console.log(reg.test('ddd'));
// 5.{n,}匹配字符>=n次
var reg = /^e{2,}$/;
console.log(reg.test(''));
console.log(reg.test('e'));
console.log(reg.test('ee'));
console.log(reg.test('eee'));
// 6.{n,m}匹配字符n到m次 n=<字符<=m
var reg = /^f{1,3}$/;
console.log(reg.test(''));
console.log(reg.test('f'));
console.log(reg.test('ff'));
console.log(reg.test('fff'));
重复方式
1.贪婪模式
尽可能多的匹配(首先取最多可匹配的数量为一组进行匹配),当匹配剩余的字符串,还会继续尝试新的匹配,直到匹配不到为止,为默认模式。
// 贪婪模式 默认模式 尽可能多的匹配字符 剩下的字符符合数量词继续匹配
// 不符合直接返回null
var reg = /\d{3,6}/g
var str = '123456789';
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));
2.非贪婪模式
尽可能少的匹配(每次取最少匹配的数量为一组进行匹配),直到匹配不到为止。
使用方法:在量词后加上 ?
// 非贪婪模式 尽可能少的匹配 当剩余字符串符合数量词最少匹配次数继续匹配
// 不符合直接返回null
var reg = /\d{3,6}?/g;
var str = '123456789';
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));
选择,分组,引用
选择
字符"|"用于分隔供选择的字符,选择项的尝试匹配次序是从左到右,直到发现了匹配项,如果左边的选择项匹配,就忽略右边的匹配项,即使它可以产生更好的匹配。
// 选择 | html|css|js 从左到右依次匹配 匹配到左侧就直接返回左侧
var reg = /html|css|js/g;
var str = 'helloworldcsshtml';
console.log(reg.exec(str));
console.log(reg.exec(str));
分组
// 分组 () briupbriupbriup
// var reg = /^briupbriupbriup$/;
var reg = /^(briup){3}$/g;
console.log(reg.test('briup'));
console.log(reg.test('briupbriup'));
console.log(reg.test('briupbriupbriup'));
console.log(reg.test('briupbriupbriupbriup'));
候选
一个分组中,可以有多个候选表达式,用 | 分隔。
// 候选 选择分组综合
var reg = /I Like (html|css|js)/;
console.log(reg.test('I Like html'));
console.log(reg.test('I Like css'));
console.log(reg.test('I Like js'));
console.log(reg.test('I Like c#'));
捕获与引用
捕获与引用
// 捕获和引用
// 捕获 将匹配到的字符串缓存起来
// 在引用之前需要校验字符串
var reg = /(\d{4})-(\d{2})-(\d{2})/;
var str = '2002-05-03';
console.log(reg.exec(str));
reg.exec(str);
// 引用
console.log(RegExp.$1); //引用第一次捕捉到的结果
console.log(RegExp.$2); //引用第二次捕捉到的结果
console.log(RegExp.$3); //引用第三次捕捉到的结果
嵌套分组的捕获
// 嵌套分组的捕获
var reg = /((cat) is (one (of)) (animals))/;
var str = 'cat is one of animals';
reg.exec(str);
console.log(RegExp.$1);
console.log(RegExp.$2);
console.log(RegExp.$3);
console.log(RegExp.$4);
console.log(RegExp.$5);
反向引用
\1引用了第一个被分组所捕获的串,换言之,表达式是动态决定的。
注意,如果编号越界了,则会被当成普通的表达式。
var reg = /(\w{4}) are \1/;
console.log(reg.test('kids are kids'));
console.log(reg.test('mans are mans'));
console.log(reg.test('kids are mans'));
console.log(reg.test('mans are kids'));
String对正则表达式的支持
search
查找字符串中是否有匹配正则的字符串,有则返回字符串第一次出现时的位置,无则返回null
正则中无论是否有全局匹配都不会影响返回结果。
// search 返回第一次出现的位置或null 有无全局匹配不影响
var reg = /hello/g;
var str = 'Oh hello world javascript';
console.log(str.search(reg));
match
匹配字符串中符合正则表达式的字符串,并返回该字符串的一个数组,其中包括字符串内容、位置。
如果正则设置全局匹配,则一次性返回所有符合正则表达式的字符串数组。
如果其中添加了分组,返回符合要求的字符串以及分组的一个数组,但如果同时开启全局匹配则不会在数组中添加分组内容。
// match 返回匹配数组 类似于exec()
// 开启全局匹配,则会把所有符合正则表达式的字符放到一个数组中
var reg1 = /hello/;
var reg2 = /hello/g;
var str = 'hello world hello javascrpt hello html';
console.log(str.match(reg1));
console.log(str.match(reg2));
split
// split 以某种形式分割字符串并将其转为数组
var reg = /\d{3}/;
var str = 'jemmy123cammy456juri';
console.log(str.split(reg));
replace
// replace 满足正则表达式的内容会被替换
var reg = /javascript/;
var str = 'Hello javascript';
var res = str.replace(reg,'java');
console.log(res,str,reg);
前瞻表达式
// 前瞻表达式
// 正向前瞻
var reg = /H(?=e)/g;
var str = 'Hello, Hi, I am Henry';
var newStr = str.replace(reg,'L');
console.log(newStr);
// 负向前瞻
var reg = /H(?!e)/g;
var str = 'Hello, Hi, I am Henry';
var newStr = str.replace(reg,'L');
console.log(newStr);
练习
1.验证是否为11位有效手机号码
以1为开头
第二位为3,4,5,7,8中的任意一位
最后以0-9的9个整数结尾
// 1.验证是否为11位有效手机号码
// - 以1为开头
// - 第二位为3,4,5,7,8中的任意一位
// - 最后以0-9的9个整数结尾
var reg = /^1[34578]{1}\d{9}/;
var str = '15821357580';
console.log(reg.test(str));
2.密码验证
匹配密码,必须包含大写,小写和数字,和特殊字符(!,@,#,%,&),且大于6位
// 2.密码验证
// 匹配密码,必须包含大写,小写和数字,和特殊字符(!,@,#,%,&),且大于6位
var reg = /^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#%&+])^[A-Za-z\d!@#%&]{6,}$/
var pwd1 = '12345a!';
var pwd2 = '12345Aa!';
console.log(reg.test(pwd1));
console.log(reg.test(pwd2));