最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

系统性学习JS正则表达式

来源:懂视网 责编:小采 时间:2020-11-27 19:46:51
文档

系统性学习JS正则表达式

系统性学习JS正则表达式:这次给大家带来系统性学习JS正则表达式,学习JS正则表达式的注意事项有哪些,下面就是实战案例,一起来看一下。一、正则表达式简介1、什么是正则表达式正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或R
推荐度:
导读系统性学习JS正则表达式:这次给大家带来系统性学习JS正则表达式,学习JS正则表达式的注意事项有哪些,下面就是实战案例,一起来看一下。一、正则表达式简介1、什么是正则表达式正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或R

2、可视化正则表达式工具

Regexper:https://regexper.com/

二、RegExp对象

实例化RegExp的两种方式。

两种方式定义RegExp对象。

1、字面量

let reg = /[a-z]{3}/gmi;
let reg = /[a-z]{3}/g;
let reg = /[a-z]{3}/m;
let reg = /[a-z]{3}/i;

标志

  • g global 代表全局搜索。如果不添加,搜索到第一个匹配停止。

  • m Multi-Line 代表多行搜索。

  • i ignore case 代表大小写不敏感,默认大小写敏感。

  • 2、构造函数

    let reg = new RegExp('\\bis\\b', 'g');

    因为JavaScript字符串中\属于特殊字符,需要转义。

    三、元字符

    把元字符当作转义字符。

    正则表达式有两种基本字符类型组成。

  • 原义文本字符

  • 元字符

  • 1、原义文本字符

    表示原本意义上是什么字符,就是什么字符。

    2、元字符

    是在正则表达式中有特殊含义的非字母字符。
    * + ? $ ^ . | \ ( ) { } [ ]

    字符含义
    \t水平制表符
    \v垂直制表符
    \n换行符
    \r回车符
    \0空字符
    \f换页符
    \cX控制字符,与X对应的控制字符(Ctrl + X)

    类似于转义字符。

    四、字符类

    表示符合某种特性的字符类别。

    使用元字符[]可以构建一个简单的类。
    所谓类是指符合某些特性的对象,一个泛指,而不是某个字符。

    例子

    表达式[abc]把字符abc归为一类,表达式可以匹配这一类中的任意一个字符。

    // replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
    'a1b2c3d4e5'.replace(/[abc]/g, '0'); //010203d4e5

    字符类取反

    我们想要替换不是abc中任意一个字符的字符。

    // 元字符 ^ 创建一个 反向类/负向类
    'abcdefg'.replace(/[^abc]/g, '0'); //abc0000

    五、范围类

    匹配这一个范围内的字符。

    如果我们想要匹配数字0-9,那么我们可能会这样写[0123456789]
    如果我们想要匹配26个字母,那么我们可能会这样写[abcdefghijklmnopqrstuvwxyz]
    这样略显麻烦,所以才会有范围类。

    例子

    // 替换所有数字
    'a1c2d3e4f5'.replace(/[0-9]/g, 'x'); //axcxdxexfx
    // 替换所有小写字母
    'a1c2d3e4f5'.replace(/[a-z]/g, 'x'); //x1x2x3x4x5
    // []组成的类内部是可以连写的。替换所有大小写字母
    'a1C2d3E4f5G6'.replace(/[a-zA-Z]/g, '*'); //*1*2*3*4*5*6

    疑问

    如果我想替换数字,并且连带-符号也一起替换呢?

    // 替换所有数字和横杠
    '2018-5-21'.replace(/[0-9-]/g, '*'); //*********

    六、预定义类

    一些已经定义的类,可以直接使用。
    字符等价类含义
    .[^\r\n]除了回车、换行之外的所有字符
    \d[0-9]数字字符
    \D[^0-9]非数字字符
    \s[\t\n\x0B\r]空白符
    \S[^\t\n\x0B\r]非空白符
    \w[a-zA-Z_0-9]单词字符(字母、数字、下划线)
    \W[^a-zA-Z_0-9]非单词字符

    例子

    替换一个 ab + 数字 + 任意字符 的字符串

    // 写法1
    'ab0c'.replace(/ab[0-9][^\r\n]/g, 'TangJinJian'); //TangJianJian
    // 写法2
    'ab0c'.replace(/ab\d./g, 'TangJinJian'); //TangJianJian

    七、单词边界

    字符含义
    ^以xxx开始(不在中括号内时的含义)
    $以xxx结束
    \b单词边界
    \B非单词边界

    例子

    我想替换的字符串,属于那种只在开头出现的。

    'YuYan is a boy, YuYan'.replace(/^YuYan/g, 'TangJinJian'); //TangJinJian is a boy, YuYan

    我想替换的字符串,属于那种只在结尾出现的。

    'YuYan is a boy, YuYan'.replace(/YuYan$/g, 'TangJinJian'); //YuYan is a boy, TangJinJian

    单词边界例子。

    // 替换所有is为0
    'This is a man'.replace(/is/g, '0'); //Th0 0 a man
    // 替换所有is前面带有单词边界的字符串
    'This is a man'.replace(/\bis/g, '0'); //This 0 a man
    // 替换所有is前面没有单词边界的字符串
    'This is a man'.replace(/\Bis\b/g, '0'); //Th0 is a man

    八、量词

    用来处理连续出现的字符串。
    字符含义
    ?出现零次或一次(最多出现一次)
    +出现一次或多次(至少出现一次)
    *出现零次或多次(任意次)
    {n}出现n次
    {n,m}出现n到m次
    {n,}至少出现n次

    我想替换字符串中连续出现10次的数字为*

    '1234567890abcd'.replace(/\d{10}/, '*'); //*abcd

    我想替换字符串中的QQ号码。

    '我的QQ是:10000'.replace(/[1-9][0-9]{4,}/, '19216811'); //我的QQ是:19216811

    九、贪婪模式

    尽可能多的匹配。

    有这样的一种场景下的正则表达式,/\d{3,6}/该替换3个数字还是6个数字呢,4、5个数字?

    // 贪婪模式会尽可能的往多的方面去匹配
    '123456789'.replace(/\d{3,6}/, 'x'); //x789
    '123456789'.replace(/\d+/, 'x'); //x
    '123456789'.replace(/\d{3,}/, 'x'); //x

    十、非贪婪模式

    尽可能少的匹配。

    如果我们想要最低限度的替换呢?

    // 非贪婪模式使用 ? 尽可能的往少的方面去匹配
    '12345678'.replace(/\d{3,6}?/g, 'x'); //xx78
    '123456789'.replace(/\d{3,6}?/g, 'x'); //xxx

    因为有g标志,会匹配这段字符串里所有符合规则的字符串。
    第一个规则/\d{3,6}?/g12345678中有两个符合条件的字符串,是123456。所以替换结果是xx78
    第二个规则/\d{3,6}?/g123456789中有三个符合条件的字符串,是123456789。所以替换结果是xxx

    十一、分组

    括号里的一些规则,分为一组。

    我想替换连续出现3次的字母数字

    //没有分组的情况下,后面的量词,只是表示匹配3次数字。
    'a1b2d3c4'.replace(/[a-z]\d{3}/g, '*'); //a1b2d3c4
    //有分组的情况下,分组后面的量词,表示符合这个分组里规则的字符串,匹配3次。
    'a1b2d3c4'.replace(/([a-z]\d){3}/g, '*'); //*c4

    1、或

    分组里有两种规则,只要满足其中一种即可匹配。

    //我想把ijaxxy和ijcdxy都替换成*
    'ijabxyijcdxy'.replace(/ij(ab|cd)xy/g, '*'); //**

    2、反向引用

    可以把分组视为变量,来引用。

    //我想把改变年月日之间的分隔符
    '2018-5-22'.replace(/(\d{4})-(\d{1,2})-(\d{1,2})/g, '$1/$2/$3'); //2018/5/22
    //我想替换日期,并且更改顺序
    '2018-5-22'.replace(/(\d{4})-(\d{1,2})-(\d{1,2})/g, '$2/$3/$1'); //5/22/2018

    3、忽略分组

    忽略掉分组,不捕获分组,只需要在分组内加上?:

    // 忽略掉匹配年的分组后,匹配月的分组变成了$1,日的分组变成了$2
    '2018-5-22'.replace(/(?:\d{4})-(\d{1,2})-(\d{1,2})/g, '$1/$2/$3'); //5/22/$3

    十二、前瞻

    正则表达式从文本头部向尾部开始解析,文本尾部方向,称为“前”。
    前瞻就是在正在表达式匹配到规则的时候,向前检查是否符合断言,后顾/后瞻方向相反。
    JavaScript不支持后顾。
    符合和不符合特定断言称为肯定/正向匹配和否定/负向匹配。
    名称正则含义
    正向前瞻exp(?=assert)
    负向前瞻exp(?!assert)
    正向后顾exp(?<=assert)JavaScript不支持
    负向后顾exp(?<!assert)JavaScript不支持

    例子

    有这样一个单词字符+数字格式的字符串,只要满足这种格式,就把其中的单词字符替换掉。

    'a1b2ccdde3'.replace(/\w(?=\d)/g, '*'); //*1*2ccdd*3

    有这样一个单词字符+非数字格式的字符串,只要满足这种格式,就把前面的单词字符替换掉。

    'a1b2ccdde3'.replace(/\w(?!\d)/g, '*'); //a*b*****e*

    十三、RegExp对象属性

    global是否全文搜索,默认false
    ignore case是否大小写敏感,默认是false
    multiline多行搜索,默认值是false
    lastIndex是当前表达式匹配内容的最后一个字符的下一个位置。
    source正则表达式的文本字符串。

    let reg1 = /\w/;
    let reg2 = /\w/gim;
    reg1.global; //false
    reg1.ignoreCase; //false
    reg1.multiline; //false
    reg2.global; //true
    reg2.ignoreCase; //true
    reg2.multiline; //true

    十四、RegExp对象方法

    1、RegExp.prototype.test()

    用来查看正则表达式与指定的字符串是否匹配。返回truefalse
    let reg1 = /\w/;
    reg1.test('a'); //true
    reg1.test('*'); //false

    加上g标志之后,会有些区别。

    let reg1 = /\w/g;
    // 第一遍
    reg1.test('ab'); //true
    // 第二遍
    reg1.test('ab'); //true
    // 第三遍
    reg1.test('ab'); //false
    // 第四遍
    reg1.test('ab'); //true
    // 第五遍
    reg1.test('ab'); //true
    // 第六遍
    reg1.test('ab'); //false

    实际上这是因为RegExp.lastIndex。每次匹配到之后,lasgIndex会改变。
    lastIndex是正则表达式的一个可读可写的整型属性,用来指定下一次匹配的起始索引。

    let reg = /\w/g;
    // 每次匹配到,就会把lastIndex指向匹配到的字符串后一个字符的索引。
    while(reg.test('ab')) {
     console.log(reg.lastIndex);
    }
    // 1
    // 2

    reg.lastIndex初始时为0,第一个次匹配到a的时候,reg.lastIndex1。第二次匹配到b的时候,reg.lastIndex2

    let reg = /\w\w/g;
    while(reg.test('ab12cd')) {
     console.log(reg.lastIndex);
    }
    // 2
    // 4
    // 6

    reg.lastIndex初始时为0,第一个次匹配到ab的时候,reg.lastIndex2。第二次匹配到12的时候,reg.lastIndex4。第三次匹配到cd的时候,reg.lastIndex6

    let reg = /\w/g;
    // 匹配不到符合正则的字符串之后,lastIndex会变为0。
    while(reg.test('ab')) {
     console.log(reg.lastIndex);
    }
    console.log(reg.lastIndex);
    reg.test('ab');
    console.log(reg.lastIndex);
    // 1
    // 2
    // 0
    // 1

    所以,这就是为什么reg.test('ab')再多次执行之后,返回值为false的原因了。

    let reg = /\w/g;
    reg.lastIndex = 2;
    reg.test('ab'); //false

    每次匹配的起始位置,是以lastIndex为起始位置的。上述例子,一开始从位置2开始匹配,位置2后面没有符合正则的字符串,所以为false

    2、RegExp.prototype.exec()

    在一个指定字符串中执行一个搜索匹配。返回一个搜索的结果数组或null

    非全局情况

    let reg = /\d(\w)\d/;
    let ts = '*1a2b3c';
    let ret = reg.exec(ts); //ret是结果数组
    // reg.lastIndex肯定是0,因为没有g标志。 没有g标志的情况下,lastIndex被忽略。
    console.log(reg.lastIndex + '\t' + ret.index + '\t' + ret.toString());
    console.log(ret);
    // 0 1 1a2,a
    // ["1a2", "a"]

    返回数组是有以下元素组成的:

  • 第一个元素是与正则表达式相匹配的文本。

  • 第二个元素是reg对象的第一个子表达式相匹配的文本(如果有的话)。

  • 第二个元素是reg对象的第二个子表达式相匹配的文本(如果有的话),以此类推。

  • // 子表达式就是分组。
    let reg = /\d(\w)(\w)(\w)\d/;
    let ts = '*1a2b3c';
    let ret = reg.exec(ts);
    console.log(reg.lastIndex + '\t' + ret.index + '\t' + ret.toString());
    console.log(ret); //
    输出结果数组 // 0 1 1a2b3,a,2,b // ["1a2b3", "a", "2", "b"]

    全局情况

    let reg = /\d(\w)(\w)(\w)\d/g;
    let ts = '*1abc25def3g';
    while(ret = reg.exec(ts)) {
     console.log(reg.lastIndex + '\t' + ret.index + '\t' + ret.toString());
    }
    // 6 1 1abc2,a,b,c
    // 11 6 5def3,d,e,f

    第一次匹配的是1abc21abc2的后一个字符的起始位置是6,所以reg.lastIndex6
    1abc2的第一个字符的起始位置是1,所以ret.index1

    第二次匹配的是5def35def3的后一个字符的起始位置是11,所以reg.lastIndex11
    5def3的第一个字符的起始位置是6,所以ret.index6

    十五、字符串对象方法

    1、String.prototype.search()

    执行正则表达式和String对象之间的一个搜索匹配。
    方法返回第一个匹配项的index,搜索不到返回-1
    不执行全局匹配,忽略g标志,并且总是从字符串的开始进行检索。

    我想知道Jin字符串的起始位置在哪里。

    'TangJinJian'.search('Jin'); //4
    'TangJinJian'.search(/Jin/); //4

    search方法,既可以通过字符串,也可以通过正则描述字符串来搜索匹配。

    2、String.prototype.match()

    当一个字符串与一个正则表达式匹配时, match()方法检索匹配项。
    提供RegExp对象参数是否具有g标志,对结果影响很大。

    非全局调用的情况

    如果RegExp没有g标志,那么match只能在字符串中,执行一次匹配。
    如果没有找到任何匹配文本,将返回null
    否则将返回一个数组,其中存放了与它找到的匹配文本有关的信息。

    let reg = /\d(\w)\d/;
    let ts = '*1a2b3c';
    let ret = ts.match(reg);
    console.log(ret.index + '\t' + reg.lastIndex);
    console.log(ret);
    // 1 0
    // ["1a2", "a"]

    非全局情况下和RegExp.prototype.exec()方法的效果是一样的。

    全局调用的情况

    我想找到所有数字+单词+数字格式的字符串。

    let reg = /\d(\w)\d/g;
    let ts = '*1a2b3c4e';
    let ret = ts.match(reg);
    console.log(ret.index + '\t' + reg.lastIndex);
    console.log(ret);
    // undefined 0
    // ["1a2", "3c4"]

    全局情况下和RegExp.prototype.exec()方法的区别。在于,没有了分组信息。
    如果我们不使用到分组信息,那么使用String.prototype.match()方法,效率要高一些。而且不需要写循环来逐个所有的匹配项获取。

    3、String.prototype.split()

    使用指定的分隔符字符串将一个String对象分割成字符串数组。
    'a,b,c,d'.split(/,/); //["a", "b", "c", "d"]
    'a1b2c3d'.split(/\d/); //["a", "b", "c", "d"]
    'a1b-c|d'.split(/[\d-|]/); //["a", "b", "c", "d"]

    4、String.prototype.replace()

    返回一个由替换值替换一些或所有匹配的模式后的新字符串。模式可以是一个字符串或者一个正则表达式, 替换值可以是一个字符串或者一个每次匹配都要调用的函数。

    常规用法

    'TangJinJian'.replace('Tang', ''); //JinJian
    'TangJinJian'.replace(/Ji/g, '*'); //Tang*n*an

    以上两种用法,是最常用的,但是还不能精细化控制。

    精细化用法

    我想要把a1b2c3d4中的数字都加一,变成a2b3c4d5

    'a1b2c3d4'.replace(/\d/g, function(match, index, orgin) {
     console.log(index);
     return parseInt(match) + 1;
    });
    // 1
    // 3
    // 5
    // 7
    // a2b3c4d5

    回调函数有以下参数:

  • match第一个参数。匹配到的字符串。

  • group第二个参数。分组,如果有n个分组,则以此类推n个group参数,下面两个参数将变为第2+n3+n个参数。没有分组,则没有该参数。

  • index第三个参数。匹配到的字符串第一个字符索引位置。

  • orgin第四个参数。源字符串。

  • 我想把两个数字之间的字母去掉。

    'a1b2c3d4e5f6'.replace(/(\d)(\w)(\d)/g, function(match, group1, group2, group3, index, orgin) {
     console.log(match);
     return group1 + group3;
    });
    // 1b2
    // 3d4
    // 5f6
    // a12c34e56相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

    推荐阅读:

    react实现选中li高亮步骤详解

    前端中排序算法实例详解

    声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文档

    系统性学习JS正则表达式

    系统性学习JS正则表达式:这次给大家带来系统性学习JS正则表达式,学习JS正则表达式的注意事项有哪些,下面就是实战案例,一起来看一下。一、正则表达式简介1、什么是正则表达式正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或R
    推荐度:
    标签: 学习 系统 js
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top