正则表达式

  数据/字符串处理是工作中经常能用到的,以前的做法大都是通过百度然后修改别人的代码完成字符串处理,一直想系统的跟正则认识一番,于是有了这篇。

点击《正则表达式》可查看原文哦!
同时非常感谢雪峰大大和鑫大大的文章支持,点击以下链接可查看参考原文。
雪峰大大的 标准对象/RegExp.
鑫大大的 粉丝群第27期JS基础小测答疑文字版

  好的,接下来进入正题啦。

正则表达式定义

  正则表达式是对字符串操作的一种逻辑公式,用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
举个例子:
  '00\d'可以匹配'007',‘008’,其中‘\d’即匹配数字。

语法

元字符

 字 符  描 述 反义字符  描 述
$匹配输入字符串的结尾位置
^匹配输入字符串的开始位置
.匹配除换行符 \n 之外的任何单字符
\b匹配单词边界\B匹配不是单词开头或结束的位置
\d匹配数字\D匹配任意非数字的字符
\w匹配字母,数字,下划线\W匹配任意不是字母,数字,下划线 的字符
\s匹配空格\S匹配任意不是空白符的字符
[abc]匹配包含括号内元素的字符[^abc]匹配除了abc以外的任意字符

量词

 字 符  描 述 带?字符  描 述
*重复至少0次*?重复任意次,但尽可能少重复
+重复至少1次+?重复至少1次,但尽可能少重复
?重复0次或1次??重复0次或1次,但尽可能少重复
{n}重复n次
{n,}重复至少n次{n,}?重复至少n次,但尽可能少重复
{n,m}重复n-m次{n,m}?重复n-m次,但尽可能少重复

特殊字符

 字 符  描 述 字 符  描 述
\cx匹配由x指明的控制字符。
\f匹配一个换页符。等价于 \x0c 和 \cL。( )标记一个子表达式的开始和结束位置。
\n匹配一个换行符。等价于 \x0a 和 \cJ。|指明两项之间的一个选择,或
\r匹配一个回车符。等价于 \x0d 和 \cM。[标记一个中括号表达式的开始
\s匹配任何空白字符,包括空格、制表符、换页符等等。\将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符
\S匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。{标记限定符表达式的开始。
\t匹配一个制表符。等价于 \x09 和 \cI。\v匹配一个垂直制表符。等价于 \x0b 和 \cK。

举例说明

  • 数字、字母匹配(\d匹配数字,\w匹配任意字母,数字,下划线)
    可用00\d可以匹配007
    \d\d\d可以匹配任意三位数字,如:123
    \w\d\w可以匹配l0l

  • .匹配任意字符,则
    any.可匹配anyaanybanycanyd ......

  • 配合上量词再看看
    \d{3}表示匹配3个数字,例如010 \d{3,8}表示3-8个数字,例如1234567

  • 再加上我们的范围
    [0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线
    [0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如a1000_ZPy3000等等
    [a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量
    [a-zA-Z\_][0-9a-zA-Z\_]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)

  • 啊,还有我们的选择字符和定位
    A|B可以匹配A或B,所以(P|p)ython可以匹配Python或者python
    ^表示行的开头,^\d表示必须以数字开头 $表示行的结束,\d$表示必须以数字结束
    你可能注意到了,py也可以匹配python,但是加上^py$就变成了整行匹配,就只能匹配py

  • 字符串的切割
    最常用的应该就是split切割了,但是当字符串之间不仅仅是单一字符连接,切割就会出现问题,比如下面的例子

     //出现多余空格情况:
        'a b   c'.split(' '); // ['a', 'b', '', '', 'c']
    
    //嗯,无法识别连续的空格,用正则表达式试试:
    'a b   c'.split(/\s+/); // ['a', 'b', 'c']
    //无论多少个空格都可以正常分割。加入,试试:
    
    'a,b, c  d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']
    //再加入;试试:
    
    'a,b;; c  d'.split(/[\s\,\;]+/); // ['a', 'b', 'c', 'd']
    //如果用户输入了一组标签,下次记得用正则表达式来把不规范的输入转化成正确的数组。
    复制代码
  • 字符串的分组应用
    除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组(Group)。比如:^(\d{3})-(\d{3,8})$分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码:

    var re = /^(\d{3})-(\d{3,8})$/;
    re.exec('010-12345'); // ['010-12345', '010', '12345']
    re.exec('010 12345'); // null
    复制代码

    如果正则表达式中定义了组,就可以在RegExp对象上用exec()方法提取出子串来。
    exec()方法在匹配成功后,会返回一个Array,第一个元素是正则表达式匹配到的整个字符串,后面的字符串表示匹配成功的子串。
    exec()方法在匹配失败时返回null。

    提取子串非常有用。来看一个更凶残的例子:

    var re = /^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$/;
    re.exec('19:05:30'); // ['19:05:30', '19', '05', '30']
    复制代码

    这个正则表达式可以直接识别合法的时间。但是有些时候,用正则表达式也无法做到完全验证,比如识别日期:

    var re = /^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$/;   
    复制代码

    对于'2-30','4-31'这样的非法日期,用正则还是识别不了,或者说写出来非常困难,这时就需要程序配合识别了。


以下内容参见鑫大大博客内容:

  • 中英文之间需要增加空格
    首先,我们的思路应该是“中文”、“英文”、“空格”,于是我们可得到 /(中文+英文+|英文+中文+)/g 这样的符号表达
    转换成正则符号即: /([\u4e00-\u9fa5]+[A-Za-z]+|[A-Za-z]+[\u4e00-\u9fa5]+)/g 其中[\u4e00-\u9fa5]表示中文字符匹配;[A-Za-z]表示全部的英文字母。斜杠后面的g表示全局匹配,除了g,还有i和m。其中i表示不区分大小写,m表示支持多行匹配。 这里的括号和加号可化简,则最终可表达为: 
    /[\u4e00-\u9fa5][a-z]|[a-z][\u4e00-\u9fa5]/gi

  • 全角标点与其他字符之间不加空格
    这里如果直接用正则表达式,会显得冗余且不易懂,故使用RegExp对象简化

    // 全角标点字符们  
    var strPunct = '!()【】『』「」《》“”‘’;:,。?、';  
    // 使用管道符连接  
    var regPunct = strPunct.split('').join('|');  
    // 此时的正则表达式  
    new RegExp('['+ regPunct +'] +| +['+ regPunct +']', 'g');  
    复制代码

    这样就显得简洁多了
    其中,空格使用普通空格字符进行匹配的,而不是\s,这样可以避免把换行符也过滤掉了

  • 不重复使用标点符号
    这里的标点指中文标点,因为英文标点不重复,有些不切实际,例如空字符串'',就是合法的重复标点。
    使用正则表达式:

    /(\~|\`|\!|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?|\!|\·|\【|\】\「\」|\;|\:|\“|\”|\,|\《|\。|\》|\、|\?)\1+/g  
    复制代码

    使用RegExp对象简化:

    new RegExp(`(${regPunct})\\1+`, 'g')
    复制代码

    这样就是不使用重复中文标点了。
    其中,这里的\1有必要好好说下。\1表示捕获匹配,表示捕获第一个分组括号中匹配的值,你可以理解为代称。在正则表达式中,每一个分组括号()都自带一个看不见的序号,从前往后依次是分组一,分组二,分组三……
    这里的\1就表示匹配的第一个标点,后面跟了个+则表示,这里重复标点2个或多个都匹配。
    捕获分组不仅存在于正则表达式中,当我们使用replace方法进行正则替换的时候,也存在与替换方法中,使用美元符号$外加数字表示,例如前后空格过滤trim()方法的简易polyfill:

    if (!''.trim) {
        String.prototype.trim = function () {
      	// $1表示第一个()中匹配的值
      	return this.replace(/^\s*(.*?)\s*$/, '$1');
        };
    }
    复制代码

    其中'$1'并不是替换成字符串$1意思,而是替换成第一个()中匹配的值,在这里表示首尾空格以外的值。 如果我们需要对捕获分组内容进行额外处理,可以把第二个参数作为function处理,例如:

    this.replace(/^\s*(.*?)\s*$/, function (matches, $1) {
        // matches表示完整匹配内容(包括前后空格)
        // $1则表示第一个()中匹配的值 
        // 此时就可以对$1进行处理,返回我们需要的值
    })
    复制代码
  • 破折号前后需要增加一个空格
    这个比较简单,可直接获得:

    /\S——|——\S/g
    复制代码
  • 使用全角中文标点
    正则表达式

    /([^A-Za-z][\~|\`|\!|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?][^A-Za-z])/g
    复制代码

    使用RegExp对象处理:

    var strPunctHalf = '!()[]"\';:,.?';
    // 不同于全角字符,半角字符需要加转义
    var regPunctHalf = strPunctHalf.split('').join('|\\');
    // 此时的正则表达式
    new RegExp(`[\u4e00-\u9fa5][a-z]*( *[${regPunctHalf}] *)|( *[${regPunctHalf}] *)[a-z]*[\u4e00-\u9fa5]`, 'gi');
    复制代码
  • 数字使用半角
    /[\uFF10-\uFF19]+/g

  • 遇到完整的英文整句,其內容使用半角标点
    正则表达式

    /(\「[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\“|\”|\,\。|\、|\?][^\」]*\」)|(\《[A-Za-z\s\~|\`|\!|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]*[\!|\·|\;|\:|\“|\”|\,\。|\、|\?][^\》]*\》)/g
    复制代码

    RegExp对象处理:

    new RegExp(`([a-z]+[${regPunct}|\\s])+[a-z]*([${regPunct}|\\s][a-z]+)+`, 'gi')
    复制代码

  正则表达式的介绍就先到这里啦,怎么样,动手使用吧~~~

转载于:https://juejin.im/post/5c510b48e51d456c767fe384

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值