JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)

目录结构

一、正则表达式-概念
二、正则表达式实践操作
1. REGEXP对象
    1)字面量
    2)构造函数
2. 元字符
3. 字符类
4. 范围类
5. JS预定义类&边界
    1)预定义类
    2)边界
6. 量词
7. JS正则贪婪模式 & 非贪婪模式
    1)贪婪模式
    2)非贪婪模式
8. 分组
9. 前瞻
10. JS对象属性
11. JS的test()方法、exec()方法
    1)RegExp.prototype.test(str)
    2)RegExp.prototype.exec(str)
12. JS字符串对象方法
    1)String.prototype.search(reg)
    2)String.prototype.match(reg)
    3)String.prototype.split(reg)
    4)String.prototype.replace()


一、正则表达式-概念

正则表达式:Regular Expression。使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。通俗而言,按照某种规则去匹配符合条件的字符串,正则表达式即匹配字符串所采用的规则。

通过正则表达式,可在IDE中处理规则复杂的字符串查找、替换需求,在JavaScript程序设计中使用正则表达式高效率处理字符串。

语法:
/正则表达式主体/修饰符(可选)
正则表达式主体:用于检索要匹配的字符
修饰符:用于对检索规则的约束or扩展

二、正则表达式实践操作

1. REGEXP对象

RegExp对象:在 JavaScript 中,RegExp 对象是一个预定义了属性和方法的正则表达式对象

JavaScript通过内置对象RegExp,支持正则表达式进行实例化RegExp对象(创建对象)有2种方法:字面量;构造函数

1)字面量

字面量:指特定的数字、字符串or布尔值,能够明确表现自己的类型并为变量进行赋值的值

示例:

let aNumber = 3         //整型字面量
let aString = "Hello"   //字符串字面量
let aBool = true        //布尔值字面量

RE.js

//定义正则表达式
var reg1 = /\bgood\b/;
var reg2 = /\bgood\b/g;
//定义字符串
var str = "good good study, day day up";
//使用replace()函数对字符串替换操作
var r1 = str.replace(reg1, "GOOD");
var r2 = str.replace(reg2, "GOOD");
var r3 = str.replace("day", "Day");
//输出替换结果
console.log(r1 + "\n" + r2 + "\n" + r3);

运行结果:

JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第1张图片

也可在浏览器的Console控制台界面对JavaScript进行操作,如下:

JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第2张图片
2)构造函数
var reg = new RegExp('\\bgood\\b', 'g');
var str = "good good study, day day up";
var r = str.replace(reg, "GOOD");
console.log(r);

以上,\b包含特殊字符,需要转义,写成\\b

修饰符
符号 含义
g global,表示全文搜索;若不添加g,则搜索到第一个匹配结果即停止匹配
i ignore case,忽略大小写;若不添加i,则默认大小写严格匹配
m multiple lines,多行搜索


2. 元字符

正则表达式由2种基本字符类型组成:

  • 1)原义文本字符:表示原来字符含义的字符。
    如:abc、123
  • 2)元字符:指有特殊含义的非字母字符。
    包括:*?$^.|\(){}[]
    如:\b 匹配边界,\n 换行,\d 数字,\s 空白字符

3. 字符类

一般情况下,正则表达式的一个字符匹配一个字符。如:abc 匹配 "abc"。对于正则匹配多个字符的场景,可使用元字符 [] 来构建一个简单的类(泛指符合某些特性的对象,非特指某个字符)。

案例1:

表达式 [abc] 把字符a、b、c归为一类,表达式可以匹配该类的任一字符(a或b或c)
实现效果:字符a、b、c都被替换成设置的A

案例2:

字符类取反(反向类/负向类)
元字符:^
含义:不属于某个类的内容
表达式:[^abc] 表示非字符(a或b或c)的内容
实现效果:匹配到a/b/c字符以外的其他字符并替换成A


4. 范围类

若以上使用字符类正则 [0123456789] 匹配数字,以及所有英文字母的匹配,写起来相对比较麻烦且效率不高。为了改善此种场景下字符类的正则写法,正则表达式提供了范围类,如:可使用 [a-z] 来匹配从a到z的任意字符(包含a和z)。

案例1:
var r = 'a1b2c3x6z9ABc'.replace(/[a-z]/g, 'Q');
console.log(r);

运行结果:
将所有的小写字母都替换成了Q

案例2:

[] 组成的类内部可以连写,如:[a-zA-z0-9] 匹配所有的大小写字母、数字字符

var r = 'a1b2c3x6z9ABc'.replace(/[a-zA-Z0-9]/g, 'Q');
console.log(r);
案例3:

在范围类之内匹配包含有连接符 - ,正则如:[0-9-]
使用范围类,在[]内字符范围之后新增连接符:

var r = '2018-12-22'.replace(/[0-9-]/g, 'Q');
console.log(r);

对比组1:使用范围类,匹配数字字符

var r = '2018-12-22'.replace(/[0-9]/g, 'Q');

对比组2:不使用范围类,直接用连接符作为正则字体

var r = '2018-12-22'.replace(/-/g, 'Q');


5. JS预定义类&边界

1)预定义类

正则表达式提供预定义类来匹配常见的字符类,常用的预定义类:.\d\D\s\S\w\W

字符 等价类 含义
. [^\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] 非单词字符

结合英文原意记忆:
d ==> digit(数字)
s ==> space(空白)
w ==> word(单词)

案例:

匹配字符串:abc+数字+任意字符
正则写法1:abc[0-9][^\r\n]
正则写法2:abc\d.

2)边界

常用的边界匹配字符:^$\b\B

字符 含义
^ 以xxx开始
$ 以xxx结束
\b 单词边界
\B 非单词边界

b ==> boundary(边界)

案例1:元字符 \b\B 的使用

对比组1:匹配字符"is",其左右皆无边界

var str = 'This is JavaScript';
var r = str.replace(/is/g, 'A');
console.log(r);

对比组2:匹配单词is,其左右皆有边界

var r = str.replace(/\bis\b/g, 'A');

对比组3:匹配字符"is",其左边无单词边界,右边有单词边

var r = str.replace(/\Bis\b/g, 'A');
案例2:元字符 ^$ 的使用

对比组1:

var str = '@999@777@';
var r = str.replace(/@./g, 'A');
console.log(r);

对比组2:

var r = str.replace(/^@./g, 'A');

对比组3:

var r = str.replace(/.@/g, 'A');

对比组4:

var r = str.replace(/.@$/g, 'A');
案例3:多行匹配(修饰符:m

对比组1:

var str = 
"@123\n@456\n@789";
var r = str.replace(/^@\d/g, 'A');
console.log(r);

对比组2:

var r = str.replace(/^@\d/gm, 'A');


6. 量词

匹配一个出现n次的字符串,n=0,1,...,N

字符 含义
? 0或1 次
+ ≥1 次
* ≥0 次(任意次)
{n} n 次
{n,m} n到m 次
{n,} ≥n 次


7. JS正则贪婪模式 & 非贪婪模式

1)贪婪模式:

尽可能多的匹配(首先取最多可匹配的数量为一组进行匹配),当匹配剩余的字符串,还会继续尝试新的匹配,直到匹配不到为止,为默认模式

案例:对字符串"123456789",匹配其中的数字3-6次:\d{3,6},并替换为特定字符
==> 先匹配数字出现6次的字符串(123456),然后再从剩余字符串(789)中匹配出现数字3次的情况,剩余字符若没有出现数字3次则停止匹配

var str = "12345678";
var r = str.replace(/\d{3,6}/g, 'A');
console.log(r);
var str = "123456789";
2)非贪婪模式:

尽可能少的匹配(每次取最少匹配的数量为一组进行匹配),直到匹配不到为止
使用方法:在量词后加上 ?

var str = "0123456789";
var r = str.replace(/\d{3,6}?/g, 'A');
console.log(r);

以上,是对 012、345、678分组匹配,剩余字符9未能再匹配

8. 分组

使用 () 进行分组,使量词作用于分组内的整体部分。如:(Candy){3}

var str = "a1b2c3d456789";
var r = str.replace(/([a-z]\d){3}/g, 'A');
console.log(r);

:使用符号 |
可联合分组符号使用,如下:

var str = "Nancy-Lucy";
var r = str.replace(/(Nan|Lu)cy/g, 'A');
console.log(r);

反向引用:使用符号 $,作为变量,捕获并引用分组内的内容

JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第3张图片
var str = "2018-12-31";
var r = str.replace(/(\d{4})-(\d{2})-(\d{2})/g, '$3/$2/$1');
console.log(r);

忽略分组:既想使用分组,又不希望捕获分组,则只需要在分组内的左侧加上符号 ?:

JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第4张图片
var str = "Date: 2018-12-31";
var r = str.replace(/(?:.*)(\d{4})-(\d{2})-(\d{2})/g, '$3/$2/$1');
console.log(r);


9. 前瞻

:正则表达式从文本头部向尾部开始解析,文本尾部方向即为“前”;预示“未来的”方向,待匹配的方向
前瞻:在正则匹配到规则时,向前检查是否符合断言;后顾/后瞻方向相反(JavaScript不支持后顾)
正向/肯定 匹配:符合特定断言
负向/否定 匹配:不符合特定断言
断言:JavaScript前瞻的语法

既要符合exp正则,又要满足断言要求

名称 正则写法 含义
正向前瞻 exp(?=assert) 符合exp正则,且符合设置的断言
负向前瞻 exp(?!assert) 符合exp正则,且不符合设置的断言

PS:以上断言部分只作为约束条件而存在,并不会参与字符本身的匹配和替换,匹配字符的是exp正则部分

案例:

约束条件:\w(?=\d),单词字符后需要紧跟着数字
匹配:\w,单词字符(字母、数字、下划线)

var str = "abc1-23_45";
var r = str.replace(/\w(?=\d)/g, 'A');
console.log(r);

以上,c1、23、_4、45都满足约束条件,则分别将会把每组符合条件的字符串中左边的单词字符替换为"A",即:A1、A3、AA5

10. JS对象属性

对象属性:

名称 含义
global g:全文搜索,默认false
ignoreCase i:大小写敏感,默认false
multiline m:多行搜索,默认false
lastIndex 下次匹配的起始位置
该属性只有设置标志g才能使用,实现遍历检索匹配
source 正则的文本字符串(正则主体)

语法:

RegExpObject.global
RegExpObject.ignoreCase
RegExpObject.multiline
RegExpObject.lastIndex
RegExpObject.source


11. JS的test()方法、exec()方法

1)RegExp.prototype.test(str)

作用:测试字符串参数中是否存在所匹配正则的字符串。若存在则返回true,否则返回false

prototype:JavaScript中的每个函数作为一个对象,每个函数对象都拥有一个子对象prototype。prototype是全局属性,适用于所有的Javascript对象,允许向对象添加属性和方法
RegExp.exec() 和 RegExp.test()方法都以 lastIndex 属性所指的位置作为下次检索的起始点,可通过反复调用这2个方法来遍历一个字符串中的所有匹配文本。当这2个方法再也找不到可以匹配的文本时,它们会自动把 lastIndex 属性重置为 0。

正则中无 g 标志:

JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第5张图片

正则中有 g 标志:

JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第6张图片

对于设置的参数,当有效匹配其中字符串时,获取对应lastIndex的取值:

JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第7张图片

以上,根据lastIndex属性指定的下一次检索起始点,正则反复调用test()方法匹配文本过程中,当匹配到文本时返回true,遍历直到未匹配到文本时返回false,然后此时test()方法将lastIndex属性重置为0;再次匹配时又会重新开始循环,因此同一个参数的同一正则连续匹配时会出现周期循环返回true和false的结果。

2)RegExp.prototype.exec(str)

使用正则对字符串执行搜索,并更新全局RegExp对象的属性,即根据lastIndex属性反映匹配结果。若字符串中有匹配的值返回该匹配值(以数组形式展示),否则返回 null

所返回结果数组的属性:
index:声明匹配文本的第1个字符的位置
input:存放被检索的字符串string

对于非全局调用:
调用非全局的RegExp对象的exec()方法时,返回的是数组,其中:
第1个元素:与正则匹配的文本
第2个元素:RegExp对象的第1个子表达式(如:分组)相匹配的文本
...
第n个元素:RegExp对象的第(n-1)个子表达式相匹配的文本

var reg3 = /\d(\w)(\w)\d/;
var reg4 = /\d(\w)(\w)\d/g;
var str = '$1ab2cd3ef4gh5ijk'
var result = reg3.exec(str);

var r3 = reg3.lastIndex + '\t' + result.index + '\t' + result.toString();
console.log(r3);

console.log('----------------');

while (result = reg4.exec(str)) {
    var r4 = reg4.lastIndex + '\t' + result.index + '\t' + result.toString();
    console.log(r4);
}
JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第8张图片


12. JS字符串对象方法

1)String.prototype.search(reg)

search()方法
用于检索字符串中指定的子字符串,or检索与正则匹配的子字符串。该方法返回第一个匹配结果的index,检索不到则返回-1;该方法将忽略标志g,不执行全局匹配,且总是从字符串的开始进行检索

JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第9张图片
JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第10张图片
2)String.prototype.match(reg)

match()方法
将检索字符串,以找到一个or多个正则匹配的文本;该方法会受到标志g的影响

非全局调用
当正则没有标志g时,match()方法只能在字符串中执行1次匹配。
若没有找到如何匹配的文本,则返回null;否则若匹配到文本,则返回一个数组,在其中存放有找到匹配文本相关的信息。所返回的数组如下:
①元素
第1个元素:存放匹配的文本
其余元素:存放于正则子表达式匹配的文本

②对象属性
index:声明匹配文本的起始字符在字符串中的位置
input:声明对String对象的引用

全局调用
当正则有标志g时,match()方法将执行全局搜索,找到字符串中所有匹配的子串。若没有找到任何匹配的子串,则返回null;若找到1个or多个匹配的子串,则返回一个数组:数组中存放字符串中所有匹配的子串,但没有index和input属性

var reg3 = /\d(\w)(\w)\d/;
var reg4 = /\d(\w)(\w)\d/g;
var str = '$1ab2cd3ef4gh5ijk'
var result = str.match(reg3);

console.log(result);

var r3 = reg3.lastIndex + '\t' + result.index + '\t' + result.toString();
console.log(r3);

console.log('----------------');

var result = str.match(reg4);
console.log(result);
var r4 = reg4.lastIndex + '\t' + result.index + '\t' + result.toString();
console.log(r4);
JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第11张图片

PS:
【1】对于非全局调用,exec()方法的参数是字符串,使用:reg.exec(str);match()方法的参数是正则表达式,使用:str.match(reg),此时两个方法的返回结果是一致的结构
【2】对于全局调用,match()方法比exec()方法匹配的数据较少(如:不会返回匹配的具体字符位置、分组信息,主要给出所匹配的子串),但match(reg)方法匹配效率更高

3)String.prototype.split(reg)

split()方法
将字符串分割为字符数组

var arr1 = 'a,b,c'.split(',');
console.log(arr1);

var arr2 = 'a,b,c,d'.split(/,/);
console.log(arr2);

var arr3 = 'a1b2c3d4e'.split(/\d/);
console.log(arr3);

var arr4 = 'a1b|c_d2e-f'.split(/[\d|_-]/);
console.log(arr4);
JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第12张图片
4)String.prototype.replace()

replace()方法
查找字符并替换为新的字符,or替换一个与正则匹配的子串
使用:

String.prototype.replace(str, replaceStr)
String.prototype.replace(reg, replaceStr)
String.prototype.replace(reg, function)
JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第13张图片

当替换值为动态值时,可考虑使用 function 函数生成替换文本
function函数中的参数:
①匹配的字符串
②正则分组内容(选填)
③匹配项在字符串中的index
④原字符串

'a1b2c3d4c5e6'.replace(/\d/g, function(match,index,origin){
    console.log(index);
    return parseInt(match)+1;
});
JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第14张图片
'1b23d45c6'.replace(/(\d)(\w)(\d)/g, function(match,group1,group2,group3,index,origin){
    console.log(match);
    return group1+group3;
});
JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法)_第15张图片



参考资料:
[1] JavaScript 正则表达式
[2] ES5基础之正则表达式02:范围类、预定义类和边界字符

在线工具:
[1] Regexper
[2] JS Bin

你可能感兴趣的:(JavaScript正则表达式(元字符|字符类|范围类|预定义类|量词|分组|前瞻|对象方法))