正则表达式用RegExp对象表示,有两种写法:
一种是字面量写法;
另一种是构造函数写法Perl写法正则表达式字面量
包含在一对斜杠(/)之间的字符,并且可以设置3个标志var expression = /pattern/flags;
flags
g:表示全局(global)模式,即模式将被应用于所有字符串,而并非在发现第一个
匹配项时立即停止
i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写
m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项test
//匹配字符串所有'at'的实例 var p = /at/g; //test()方法返回一个布尔值表示是否可以找到匹配项 console.log(p.test('ata'));//true console.log(p.test('aba'));//false
RegExp构造函数
和普通的内置对象一样,RegExp正则表达式对象也支持new RegExp()构造函数的形式
RegExp构造函数接收两个参数:要匹配的字符串模式(pattern)和可选的标志字符串(flags),标志字符串和字面量的三个标志含义相同:’g’、’i’、’m’
RegExp构造函数的两个参数都是字符串。且使用字面量形式定义的任何表达式都可使用构造函数
//匹配字符串所有'at'的实例 var p1 = /at/g; //同上 var p2 = new RegExp('at','g');
元字符
元字符 名称 匹配对象
. 点号 单个任意字符(除回车\r、换行\n、行分隔符\u2028和段分隔符\u2029外)
[] 字符组 列出的单个任意字符
[\^] 排除型字符组 未列出的单个任意字符
? 问号 匹配0次或1次
* 星号 匹配0交或多次
+ 加号 匹配1次或多次
{min,max} 区间量词 匹配至少min次,最多max次
^ 脱字符 行的起始位置
$ 美元符 行的结束位置
| 竖线 分隔两边的任意一个表达式
() 括号 限制多选结构的范围,标注量词作用的元素,为反向引用捕获文本
\1,\2… 反向引用 匹配之前的第一、第二…组括号内的表达式匹配的文本转义字符
转义字符(escape)表示为反斜线()+字符的形式
右方括号]和右花括号}不需要转义console.log(/1+1/.test('1+1')); //false console.log(/1\+1/.test('1+1')); //true console.log(/\*/.test('*')); //true console.log(/*/.test('*')); //报错
\0 NUL字符\u0000
[\b] 匹配退格符\u0008,不要与\b混淆
\t 制表符\u0009
\n 换行符\u000A
\v 垂直制表符\u000B
\f 换页符\u000C
\r 回车符\u000D
\xnn 由十六进制数nn指定的拉丁字符
\uxxxx 由十六进制数xxxx指定的Unicode字符(\u4e00-\u9fa5代表中文)
\cX 控制字符^X,表示ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符‘\’加任意其他字符,默认情况就是匹配此字符,也就是说,反斜线()被忽略了
console.log(/\x/.test('x')); //true console.log(/\y/.test('y')); //true console.log(/\z/.test('z')); //true
由于RegExp构造函数的参数是字符串,所以某些情况下,需要对字符进行双重转义
字符\在正则表达式字符串中通常被转义为\
var p1 = /\.at/; //等价于 var p2 = new RegExp('\\.at'); var p1 = /name\/age/; //等价于 var p2 = new RegExp('name\\/age'); var p1 = /\w\\hello\\123/; //等价于 var p2 = new RegExp('\\w\\\\hello\\\\123');
字符组
1.方括号表示的一组字符,它匹配若干字符之一//匹配0-9这10个数字之一 var p = /[0123456789]/; p.test('1');//true p.test('a');//false
2.正则表达式通过连字符(-)提供了范围表示法,可以简化字符组
/[0123456789]/ //等价于 /[0-9]/ /[abcdefghijklmnopqrstuvwxyz]/ //等价于 /[a-z]/
在字符组中可以同时并列多个’-‘范围
/[0-9a-zA-Z]/;//匹配数字、大写字母和小写字母 /[0-9a-fA-F]/;//匹配数字,大、小写形式的a-f,用来验证十六进制字符 console.log(/[0-9a-fA-F]/.test('d'));//true console.log(/[0-9a-fA-F]/.test('x'));//false
3.排除^
字符组的另一个类型是排除型字符组,在左方括号后紧跟一个脱字符’^’表示,表示在当前位置匹配一个没有列出的字符 所以[^0-9]表示0-9以外的字符
在字符组内部,脱字符’^’表示排除,而在字符组外部,脱字符’^’表示一个行锚点^符号是元字符,在字符组中只要^符号不挨着左方括号就可以表示其本身含义,不转义也可以
//匹配abc和^符号 console.log(/[a-c^]/.test('^'));//true console.log(/[a-c\^]/.test('^'));//true console.log(/[\^a-c]/.test('^'));//true
在字符组中,只有^、-、[、]这4个字符可能被当做元字符,其他有元字符功能的字符都只表示其本身
console.log(/[[1]]/.test('['));//false console.log(/[[1]]/.test(']'));//false console.log(/[\1]/.test('\\'));//false console.log(/[^^]/.test('^'));//false console.log(/[1-2]/.test('-'));//false console.log(/[\[1\]]/.test('['));//true console.log(/[\[1\]]/.test(']'));//true console.log(/[\\]/.test('\\'));//true console.log(/[^]/.test('^'));//true console.log(/[1-2\-]/.test('-'));//true
简记
用[0-9]、[a-z]等字符组,可以很方便地表示数字字符和小写字母字符。对于这类常用字符组,正则表达式提供了更简单的记法,这就是字符组简记(shorthands)常见的字符组简记有\d、\w、\s。其中d表示(digit)数字,w表示(word)单词,s表示(space)空白
正则表达式也提供了对应排除型字符组的简记法:\D、\W、\S。字母完全相同,只是改为大写,这些简记法匹配的字符互补
\d 数字,等同于[0-9] \D 非数字,等同于[^0-9] \s 空白字符,等同于[\f\n\r\t\u000B\u0020\u00A0\u2028\u2029] \S 非空白字符,等同于[^\f\n\r\t\u000B\u0020\u00A0\u2028\u2029] \w 字母、数字、下划线,等同于[0-9A-Za-z_](汉字不属于\w) \W 非字母、数字、下划线,等同于[^0-9A-Za-z_]
任意字符
人们一般认为点号可以代表任意字符,其实并不是.点号代表除回车(\r)、换行(\n) 、行分隔符(\u2028)和段分隔符(\u2029)以外的任意字符
妥善的利用互补属性,可以得到一些巧妙的效果。比如,[\s\S]、[\w\W]、[\d\D]都可以表示任意字符
//匹配任意字符 console.log(/./.test('\r'));//false console.log(/[\s\S]/.test('\r'));//true
量词
{n} 匹配n次
{n,m} 匹配至少n次,最多m次
{n,} 匹配至少n次
? 相当于{0,1}
* 相当于{0,}
+ 相当于{1,}//表示邮政编码6位数字 /\d{6}/;
//美国英语和英国英语有些词的写法不一样,如果traveler和traveller,favor和favour,color和colour //同时匹配美国英语和英国英语单词 /travell?er/; /favou?r/; /colou?r/;
贪婪模式
默认情况下,量词都是贪婪模式(greedy quantifier),即匹配到下一个字符不满足匹配规则为止//exec()方法以数组的形式返回匹配结果 /a+/.exec('aaa'); // ['aaa']
懒惰模式
懒惰模式(lazy quantifier)和贪婪模式相对应,在量词后加问号’?’表示,表示尽可能少的匹配,一旦条件满足就再不往下匹配复制代码
{n}? 匹配n次
{n,m}? 匹配至少n次,最多m次
{n,}? 匹配至少n次
?? 相当于{0,1}
*? 相当于{0,}
+? 相当于{1,}/a+?/.exec('aaa'); // ['a']
括号
括号有两个功能,分别是分组和引用。具体而言,用于限定量词或选择项的作用范围,也可以用于捕获文本并进行引用或反向引用
1.分组量词控制之前元素的出现次数,而这个元素可能是一个字符,也可能是一个字符组,也可以是一个表达式
如果把一个表达式用括号包围起来,这个元素就是括号里的表达式,被称为子表达式
如果希望字符串’ab’重复出现2次,应该写为(ab){2},而如果写为ab{2},则{2}只限定b
console.log(/(ab){2}/.test('abab'));//true console.log(/(ab){2}/.test('abb'));//false console.log(/ab{2}/.test('abab'));//false console.log(/ab{2}/.test('abb'));//true
2.捕获
括号不仅可以对元素进行分组,还会保存每个分组匹配的文本,等到匹配完成后,引用捕获的内容。因为捕获了文本,这种功能叫捕获分组比如,要匹配诸如2016-06-23这样的日期字符串
/(\d{4})-(\d{2})-(\d{2})/
RegExp.$1\RegExp.$2\RegExp.$3……到RegExp.$9分别用于存储第一、第二……第九个匹配的捕获组。在调用exec()或test()方法时,这些属性会被自动填充
console.log(/(\d{4})-(\d{2})-(\d{2})/.test('2016-06-23'));//true console.log(RegExp.$1);//'2016' console.log(RegExp.$2);//'06' console.log(RegExp.$3);//'23' console.log(RegExp.$4);//''
捕获分组捕获的文本,不仅可以用于数据提取,也可以用于替换
replace()方法就是用于进行数据替换的,该方法接收两个参数,第一个参数为待查找的内容,而第二个参数为替换的内容
console.log('2000-01-01'.replace(/-/g,'.'));//2000.01.01
在replace()方法中也可以引用分组,形式是$num,num是对应分组的编号
//把2000-01-01的形式变成01-01-2000的形式 console.log('2000-01-01'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$3-$2-$1'));//'01-01-2000'
3.非捕获
除了捕获分组,正则表达式还提供了非捕获分组(non-capturing group),以(?:)的形式表示,它只用于限定作用范围,而不捕获任何文本
比如,要匹配abcabc这个字符,一般地,可以写为(abc){2},但由于并不需要捕获文本,只是限定了量词的作用范围,所以应该写为(?:abc){2}
console.log(/(abc){2}/.test('abcabc'));//true console.log(/(?:abc){2}/.test('abcabc'));//true
由于非捕获分组不捕获文本,对应地,也就没有捕获组编号
console.log(/(abc){2}/.test('abcabc'));//true console.log(RegExp.$1);//'abc' console.log(/(?:abc){2}/.test('abcabc'));//true console.log(RegExp.$1);//''
选择
竖线’|’在正则表达式中表示或(OR)关系的选择,以竖线’|’分隔开的多个子表达式也叫选择分支或选择项。在一个选择结构中,选择分支的数目没有限制断言
正则表达式中,有些结构并不真正匹配文本,而只负责判断在某个位置左/右侧是否符合要求,这种结构被称为断言(assertion),也称为锚点(anchor),常见的断言有3种:单词边界、行开头结尾、环视1.单词边界
在文本处理中可能会经常进行单词替换,比如把row替换成line。但是,如果直接替换,不仅所有单词row都被替换成line,单词内部的row也会被替换成line。要想解决这个问题,必须有办法确定单词row,而不是字符串row 为了解决这类问题,正则表达式提供了专用的单词边界(word boundary),记为\b,它匹配的是'单词边界'位置,而不是字符。\b匹配的是一边是单词字符\w,一边是非单词字符\W的位置 与\b对应的还有\B,表示非单词边界,但实际上\B很少使用
console.log(/\ban\b/.test('an apple'));//true console.log(/\ban\b/.test('a an'));//true console.log(/\ban\b/.test('an'));//true console.log(/\ban\b/.test('and'));//false console.log(/\ban\b/.test('ban'));//false
2.起始结束
常见的断言还有^和$,它们分别匹配字符串的开始位置和结束位置,所以可以用来判断整个字符串能否由表达式匹配
//匹配第一个单词 console.log(/^\w*/.exec('first word\nsecond word\nthird word'));//['first'] //匹配最后一个单词 console.log(/\w*$/.exec('first word\nsecond word\nthird word'));//['word'] console.log(/^a$/.test('a\n'));//false console.log(/^a$/.test('a'));//true
^和$的常用功能是删除字符串首尾多余的空白,类似于字符串String对象的trim()方法
function fnTrim(str){ return str.replace(/^\s+|\s+$/,'') } console.log(fnTrim(' hello world '));//'hello world'
3.环视
环视(look-around),可形象地解释为停在原地,四处张望。环视类似于单词边界,在它旁边的文本需要满足某种条件,而且本身不匹配任何字符 环视分为正序环视和逆序环视,而javascript只支持正序环视,相当于只支持向前看,不支持往回看 而正序环视又分为肯定正序环视和否定正序环视 肯定正序环视的记法是(?=n),表示前面必须是n才匹配;否定正序环视的记忆法是(?!n),表示前面必须不是n才匹配
console.log(/a(?=b)/.exec('abc'));//['a'] console.log(/a(?=b)/.exec('ac'));//null console.log(/a(?!b)/.exec('abc'));//null console.log(/a(?!b)/.exec('ac'));//['a'] console.log(/a(?=b)b/.exec('abc'));//['ab']
匹配模式
匹配模式(match mode)指匹配时使用的规则。设置特定的模式,可能会改变对正则表达式的识别。前面已经介绍过创建正则表达式对象时,可以设置’m’、’i’、’g’这三个标志,分别对应多行模式、不区分大小模式和全局模式三种i
默认地,正则表达式是区分大小写的,通过设置标志’i’,可以忽略大小写(ignore case)console.log(/ab/.test('aB'));//false console.log(/ab/i.test('aB'));//true
m
默认地,正则表达式中的^和$匹配的是整个字符串的起始位置和结束位置,而通过设置标志’m’,开启多行模式,它们也能匹配字符串内部某一行文本的起始位置和结束位置console.log(/world$/.test('hello world\n')); //false console.log(/world$/m.test('hello world\n')); //true console.log(/^b/.test('a\nb')); //false console.log(/^b/m.test('a\nb')); //true
g
默认地,第一次匹配成功后,正则对象就停止向下匹配了。g修饰符表示全局匹配(global),设置’g’标志后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换console.log('1a,2a,3a'.replace(/a/,'b'));//'1b,2a,3a' console.log('1a,2a,3a'.replace(/a/g,'b'));//'1b,2b,3b'
优先级
正则表达式千变万化,都是由之前介绍过的字符组、括号、量词等基本结构组合而成的//从上到下,优先级逐渐降低
\ 转义符
() (?!) (?=) [] 括号、字符组、环视-
- ? {n} {n,} {n,m} 量词
^ $ 起始结束位置
| 选择
- ? {n} {n,} {n,m} 量词
-
js正则
最新推荐文章于 2023-04-21 13:11:05 发布