JavaScript正则表达式
正则表达式总是用的稀里糊涂的,最近看到imooc上 Samaritan89老师的一个视频JavaScript正则表达式,讲解的很清楚,这里是关于视频的笔记以及自己的理解。不过若是只是日常使用不是精通,正则表达式其实是不难的,不要有畏惧心理。 ^^
正则表达式对象
创建正则表达式对象有两种方式: 字面量 与 构造函数
字面量
1var reg1 = /\bis\b/gi;注意是没有’’或者“” 的,那样是字符串。
构造函数
1var reg2 = new RegExp('\\bis\\b','gi')修饰符: 1) g: global 是全局 ,表示进行全局搜索 2) i: ignore 忽略掉大小写 3) m: 多行搜索
123var str1 ="He is a student, Is he "console.log(str1.replace(reg1,'00')) // He 00 a student, 00 heconsole.log(str1.replace(reg2,'00')) // He 00 a student, 00 he对象属性
正则表达式变量是对象类型,在这种对象类型上有几种对象属性
属性名 | 属性含义 |
---|---|
global | 是否全文搜索 ,默认值是false,只读属性 |
ignoreCase | 是否忽略大小写,默认值是false,只读属性 |
multiline | 是否多行搜索,默认值是false,只读属性 |
lastIndex | 当前表达式匹配内容的最后一个字符的下一个位置即下次搜索开始时的索引值 |
source | 正则表达式的文本字符串 |
|
|
元字符
正则表达式中由两种基本字符类组成:原义文本字符 和 元字符。 元字符是在正则表达式中含有特殊含义的非字母字符。 如上面例子中的’\b’是匹配一个单词边界是属于元字符。除此之外还需要注意的是 : * + ? ¥ ^ . | () {} []
这些符号都是由着特殊含义的元字符。这些符号在不同的场景下会有不同的语义。 还有一些常见的元字符:
字符 | 含义 |
---|---|
\t | 水平制表符 |
\v | 垂直制表符 |
\n | 换行符 |
\r | 回车符 |
\0 | 空字符 |
\f | 换页符 |
\cX | 与X对应的控制字符(Ctrl+X) |
更多元字符解释 参见Regular Expressions MDN
字符类
一般情况下正则表达式一个字符对应字符串一个字符。
某些情况下需要使用一个字符对应一类字符。 这时可以使用元字符[]来构造一个简单的类。所谓的类是指符合某些特性的对象,一个泛指,而不是特指某个字符。
如表达式[abc]把字符a 或b 或c 归为一类,表达式可以匹配这类的字符。在[]内的^表示取反。
范围类
在[] 用-
连起来表示一个范围,如[a-z]表示从a-z的字母。在范围类中一次可以连写的如[a-zA-Z]。
若是匹配如”2017-05-26”中的’-‘可以在后面直接加’-‘,在数字之间或者字母之间的’-‘表示范围否则表示单个的’-‘符号。
|
|
[]表示范围类,如[xyz]表示x或者y或者z , xyz 与(xyz)表示的是“xyz” ;[^xyz]表示的也是不是xyz中的一个,而不是只不是x。
预定义类及边界
正则表达式提供了常见的预定义类来匹配一下常见的字符类。
字符 | 等价类 | 含义 |
---|---|---|
. | [^\r\n] | 除了回车符和换行符之外的所有字符 |
\d | [0-9] | 数字字符 |
\D | [^0-9] | 非数字字符 |
\s | [\t\n\x0B\f\r] | 空白字符 |
\S | [\t\n\x0B\f\r] | 非空白字符 |
\w | [a-zA-Z_0-9] | 单词字符(字母、数字下划线) |
\W | [a-zA-Z_0-9] | 非单词字符 |
栗子: 显示‘ab’+数字+任意字符
|
|
正则表达式还提供了几个常用边界匹配字符。
字符 | 含义 |
---|---|
^ | 以XX开始 |
$ | 以XX结束 |
\b | 单词边界 |
\B | 非单词边界 |
|
|
量词
正则表达式提供了一些字符来表示量词。
字符 | 含义 |
---|---|
? | 出现0次或1次(最多出现一次) |
+ | 出现1次或多次(至少出现一次) |
* | 出现零次或多次(任意次) |
{n} | 出现n次 |
{n,m} | 出现n到m次 |
{n,} | 至少出现n次 |
JavaScript 贪婪模式与非贪婪模式
正则表达式在匹配时会尽可能多的匹配直到匹配失败,即正常情况下就是出于贪婪模式。
栗子:
对于非贪婪模式是让正则表达式尽可能少的匹配,也就是一旦匹配成功就不再尝试。 方法就是在量词后面加上?即表示非贪婪模式。
分组
使用() 可以进行分组,这样量词就可以作用于分组而不是紧邻着的字符。
栗子:
使用“|”表示或
反向引用: 可以用$1…等进行分组捕获
栗子
反向引用是需要进行分组的,若是想忽略掉某一个分组则在这个分组的首部添加 ?:
栗子
前瞻
正则表达式是从文本头部向文本尾部进行解析,所以从文本头部向文本尾部的方向被称为“前向”。 前瞻
就是在正则表达式匹配到规则的时候,向前检查是否符合断言。后顾的方向相反。 符合和不符合特定断言称为肯定/正向匹配 和否定/负向匹配。
在JavaScript中没有后顾。
名称 | 正则 | 含义 |
---|---|---|
正向前瞻 | exp(?=assert) | |
负向前瞻 | exp(?!assert) | |
正向后顾 | exp(?<=assert) | JavaScript不支持 |
负向后顾 | exp(?<!assert) | JavaScript不支持 |
|
|
正则表达式对象方法 —test 与exect 方法
正则表达式对象方法的test方法用来测试一个字符串是否符合表达式,返回结果是true 或者false。但是需要注意的是 当正则表达式是否含有全局修饰符时表现会有不同。
栗子:1234567891011var reg7 = /\w/var reg8 = /\w/gconsole.log(reg7.test('ab')) // trueconsole.log(reg7.test('ab')) // trueconsole.log(reg7.test('ab')) // trueconsole.log(reg8.test('ab')) // trueconsole.log(reg8.test('ab')) // trueconsole.log(reg8.test('ab')) // falsewhile(reg8.test('ab')){console.log(reg8.lastIndex) // 1 2}正则表达式对象方法的exec方法是可以用来匹配一个字符串,返回的是数组或者null。 当返回的是数组的时候第一个值是匹配的字符串,之后是匹配的分组的值,然后是匹配的字符串开始的索引index属性,最后一个是用来检测的字符串的source属性。exec方法和test方法在当正则表达式是有全局修饰符g时表现会不同。看栗子:
12345678var reg9=/\d(\w)(\w)\d/;var reg10=/\d(\w)(\w)\d/g;var str="1aa2bb3cc4";console.log(reg9.exec(str)) // [ '1aa2', 'a', 'a', index: 0, input: '1aa2bb3cc4' ]console.log(reg9.exec(str)) // [ '1aa2', 'a', 'a', index: 0, input: '1aa2bb3cc4' ]console.log(reg10.exec(str)) // [ '1aa2', 'a', 'a', index: 0, input: '1aa2bb3cc4' ]console.log(reg10.exec(str)) // [ '3cc4', 'c', 'c', index: 6, input: '1aa2bb3cc4' ]console.log(reg10.exec(str)) // null
字符串对象方法—search、match、split、replace
String.prototype.search(regRex) 用于检测字符串中的指定字符串,若是存在返回第一个匹配结果的index,否则范回-1。search() 方法不执行全局匹配,忽略g标志每次总是从开始位置进行搜索。
String.prototype.match(regRex) 用于检索字符串中的指定的字符串,以找到一个或多个与regRex相匹配的文本。当正则表达式是否含有g 结果差别是很大的。
当是非全局匹配的时候,match方法类似于exec方法。 当时全局匹配的时候,match方法只返回匹配的字符串,没有index,与input属性。1234console.log(str.match(reg9)) // [ '1aa2', 'a', 'a', index: 0, input: '1aa2bb3cc4' ]console.log(str.match(reg9)) // [ '1aa2', 'a', 'a', index: 0, input: '1aa2bb3cc4' ]console.log(str.match(reg10)) // [ '1aa2', '3cc4' ]console.log(str.match(reg10)) // [ '1aa2', '3cc4' ]String.prototype.split(regRex)
1console.log('a1a2a3a4z'.split(/\d/)) // [ 'a', 'a', 'a', 'a', 'z' ]String.prototype.replace(string,replaceString) ,String.prototype.replace(regRex,replaceString) ,String.prototype.replace(regRex,function)
对于第二个参数是function的replace用法:
1234var s2 = 'a1b2c3d4e5'.replace(/(\d)(\w)(\d)/g,function(match,group1,group2,group3,index,original){return group1+group3})console.log(s2)// a12c34e5
用正则表达式进行日期的格式化
function formatDate(date, fmt) {
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear()) + '').substr(4 - RegExp.$1.length)
}
let o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds()
}
for (let k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
let str = o[k] + ''
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str))
}
}
return fmt
}
function padLeftZero(str) {
return ('00' + str).substr(str.length)
}