详解正则化表达式(附有实例练习)

为什么存在?

  典型的搜索与替换操作要求提供与预期的搜索结果匹配的确切文本,虽然该技术对静态文本执行简单搜索和替换任务可能已经足够了,但它缺乏灵活性,若采用该方法搜索动态文本,虽然有可能实现目的,但是过程也是很困难。但是!
    通过使用正则表达式,可以:
        ①测试字符串内的模式
            如:可测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式,这称为数据验证
        ②替换文本
            可使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其它文本替换它
        ③基于模式匹配从字符串中提取子字符串
            可以查找文档内或输入域内特定的文本

是什么?

  正则化表达式是一种文本模式,包括普通字符(如a到z之间的字母)和特殊字符(称为"元字符"),它使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串

分类?

  普通字符:

     普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。包括所有大写和小写字母、所有数字、所有标点符号和一些其它符号;

        [ABC]            ----匹配[...]中的所有字符
            举例:[eap] 匹配 "I Love China!"中的所有e a p字符 
        [^ABC]          ----匹配除了[...]中字符的所有字符
            举例:[^eap]匹配字符串"I Love China"中除了e a p字母的所有字母
        [A-Z]              ----表示一个区间,匹配所有大写字母
        [a-z]               ----表示一个区间,匹配所有小写字母
        .                     ----匹配除换行符(\n、\r)之外的任何单个字符,相当于[^\n\r]
        [\s\S]              ----匹配所有。\s是匹配所有空白符,包括换行,\S非空白符,不包括换行
        \w                   ----匹配字母、数字、下划线。相当于[A-Za-z0-9_-]
        \W                  ----匹配非字母、数字、下划线。相当于[^A-Za-z0-9_-]
        \cx                  ----匹配由x指明的控制字符
              举例:\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一,否则,将c视为一个原义的'c'字符
        \f                    ----匹配一个换页符,等价于\x0c和\cL
        \n                   ----匹配一个换行符。等价于\x0a和\cJ
        \r                    ----匹配一个回车符。等价于\x0d和\cM
        \s                    ----匹配任何空白字符,包括空格、制表符、换页符等。等价于[\f\n\r\t\v]。注意Unicode正则表达式会匹配全角空格符
        \S                   ----匹配任何非空白字符。等价于[^\f\n\r\t\v]
        \t                     ----匹配一个制表符。等价于\x09和\cl
        \v                    ----匹配一个垂直制表符。等价于\x0b和\cK

特殊字符:
    特殊字符就是一些有特殊含义的字符,如*表示任何字符串,若要匹配这些特殊字符,首先使字符"转义",即在其前面加一个\,如baid\*u匹配字符串baidiu
        $                   ----匹配输入字符串的结尾位置    
        ()                   ----标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用,要匹配这些字符,请使用\( 和\)
        *                    ----匹配前面的子表达式零次或多次
        +                   ----匹配前面的子表达式一次或多次
        .                    ----匹配除换行符\n之外的任何单字符
        [                    ----标记一个中括号表达式的开始
        ?                 ----匹配前面的子表达式零次或一次,或指明一个非贪婪限定符
        ^                   ----匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合
        {                    ----标记限定符表达式的开始
        |                    ----指明两项之间的一个选择

限定符:
    限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。共有*  +  ?  {n}  {n,}  {n,m}6种
        *                   ----匹配前面的子表达式零次或多次
        +                  ----匹配前面的子表达式一次或多次
        ?                 ----匹配前面的子表达式零次或一次
        {n}                ----n是一个非负整数。匹配确定的n次
        {n,}               ----n是一个非负整数。至少匹配n次
        {n,m}            ----m和n均为非负整数,n<=m。最少匹配n次,请注意在逗号和两个数之间不能有空格

定位符:
    定位符能够将正则表达式固定到行首或行尾,^和$分别指字符串的开始与结束,\b描述单词的前或后边界,即字与空格间的位置,\B表示非单词边界
    举例:如单词Chapter
        /\bCha/        ----匹配单词开头三个字符,\b匹配单词边界,而这三个字符出现在单词边界后面
        /ter\b/           ----匹配单词结尾三个字符
        即:\b位置很重要:若位于要匹配的字符串的开始,则在被搜索的字符串开始处查找匹配项;若位于字符串的结尾,则在被搜索字符串的结尾处查找匹配项
        /\Bapt/          ----匹配单词Chapter中的apt,但是不匹配aptitude中的字符串apt(因为\B是非单词边界)

选择:

    用圆括号()将所有选择项括起来,相邻的选择项之间用|分隔
    ()用于捕获分组,()会把每个分组里的匹配的值保存起来,多个匹配值可以通过数字n来查看(n是一个数字,表示第n个捕获组的内容)
    但用圆括号会有一个副作用,使相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用
    ?= 正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串
    ?! 负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串
    重要:?=、?<=、?!、?<!的使用区别
        exp1(?=exp2)                    ----查找后面是exp2的exp1
             例: /ok(?=[\d+])/g    匹配数字前的ok ps:\d匹配一个数字字符。等价于[0-9];\D匹配一个非数字字符。等价于[^0-9]
        (?<=exp2)exp1                  ----查找前面是exp2的exp1
            例:/(?<=[0-9]+)baidu     ----匹配数字后面的baidu
        exp1(?!exp2)                     ----查找后面不是exp2的exp1
            例:/baidu(?![0-9]+)        ----匹配后面不是数字的baidu
        (?<!exp2)exp1                   ----查找前面不是exp2的exp1
            例:/(?<![0-9]+)baidu      ----匹配前面不是数字的baidu
    通俗来讲:
        ?=和?<=表示查找符合要求的,?!和?<!表示查找不符合要求的;
        带<的表示放在前面,表前面是/不是....的字符串,反之表示后面是/不是....的字符串
    补充:
        (pattern)      ----匹配pattern并获取这一匹配
        (?:pattern)    ----匹配pattern但不获取匹配结果,即为非获取匹配,不进行存储供以后使用
        (?=pattern)    ----正向肯定预查,在任何匹配pattern的字符串开始处匹配字符串,是非获取匹配预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始

反向引用?

   对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓存区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右的顺序存储。缓冲区编号从1开始,最多可存储99个捕获的字表达式每个缓冲区都可以使用\n访问其中n为一个标识特定缓冲区的一位或两位十进制数
    可以使用非捕获元字符?:、?=或?!来重写捕获,忽略对相关匹配的保存
    他最简单、最有用的应用之一,是提供查找文本中两个相同的相邻单词的匹配项的能力:
        举例: Is is the const of of gosoline going up up?定位该句子,而不必查找每个单词的重复出现
        var str = "Is is the const of of gosoline going up up?";
        var patt1 = /\b([a-z]+)\1\b/ig;
        document.write(str.match(patt1));
        解析:捕获的表达式,正如[a-z]+指定的,包括一个或多个字母。正则表达式的第二部分是对以前捕获的子匹配项的应用,即单词的第二个匹配项正好由括号表达式匹配
            \1指定第一个子匹配项
            单词边界元字符\b确保只检测整个单词
            /ig 全局并且不区分大小写匹配
    注意:索引0对应的是整个字符串,索引1对应第一个匹配符
        又例:
            var str = "http://www.baidu.com:80/introduction/.html";
            var patt1 = /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/;
            arr = str.match(patt1);
            for (var i = 0; i < arr.length ; i++) {
                document.write(arr[i]);
                document.write("<br>");
            }
        解析:
            第三行代码str.match(patt1)返回一个数组。实例中的数组包含5个元素,索引0对应的是整个字符串,索引1对应第一个匹配符,一次类推
            第一个括号子表达式捕获web地址的协议部分。该子表达式匹配在冒号和两个正斜杠前面的任何单词
            第二个括号子表达式捕获地址的域地址部分,该子表达式匹配非:和/之后的一个或多个字符。
            第三个括号子表达式捕获端口号。该子表达式匹配冒号后面的零个或多个数字,只能重复一次该子表达式
            第四个括号子表达式捕获web地址指定的路径和/或页信息。该子表达式能匹配不包括#或空格字符的任何字符序列
            将正则表达式应用到上面的 URI,各子匹配项包含下面的内容:
                第一个括号子表达式包含 http
                第二个括号子表达式包含 www.baidu.com
                第三个括号子表达式包含 :80
                第四个括号子表达式包含 /introduction/.html

修饰符?

   修饰符也称作标记,用于指定额外的匹配策略
   修饰符不写在正则表达式里,标记位于表达式之外,格式如下:
        /pattern/flags
   常用的修饰符如下:
        i     ----不区分大小写(ignore)
        g     ----全局匹配(global)
        m     ----多行匹配(multi line),不是整个字符串的开头和结尾
        s     ----默认情况下的圆点.是匹配除换行符\n之外的任何字符,加上s修饰符之后,.中包含换行符\n

贪婪与非贪婪?

   *和+限定符都是贪婪的,因为它们会尽可能多的匹配文字,但是只要在它们的后面加上一个?就可以实现非贪婪或最小匹配。
        例如: 假设有代码<p1>今天是个美好的日子</p1>
        贪婪: /<.*>/            ----就会匹配从开始小于符号(<)到关闭h1标记的大于符号(>)之间的所有内容<p1>今天是个美好的日子</p1>
        非贪婪: /<.*?>          ----匹配<p1>
    注意:不能够将限定符与定位符一起使用(因为在紧靠换行或者单词边界的前面或后面不能有一个以上位置,因此不允许诸如^*之类的表达式)

总结

 字符簇:放在[ ]里面的字符,括在中括号表达式中的字符只匹配处于正则表达式中该位置的单个字符
 确定重复出现:跟在字符或字符簇后面的花括号{ }用来确定前面的内容的重复出现的次数
        {x}表示前面的字符或字符簇只出现x次;
        {x,}表示前面的内容出现大于x次;
        {x,y}表示前面的内容至少出现x次,但不超过y次
        特殊字符*与{0,}是相等的,代表大于等于0次的前面的内容
        特殊字符+与{1,}是相等的,代表大于等于1次前面的内容
        特殊字符?与{0,1}是相等的,代表0个或一个前面的内容

举例

用户注册表单时,只允许用户名包含字符、数字、下划线和连接字符(-),并设置用户名的长度为6-20,就可以用如下表达式来设定。
        ^[a-z0-9_-]{6,20}$     // ^开始标记;[a-z0-9_-]字母(a-z)数字(0-9)下划线_连字符;{6,20}表示前面字符重复次数;$结束标记

②不包含全角符号

       ^[^()]+$

③合法年份

       ^[1-9][0-9]{3}$

④格式为YYYYMMDD的合法日期

      ^((\d{3}[1-9]|\d{2}[1-9]\d|\d[1-9]\d{2}|[1-9]\d{3})(((0[13578]|1[02])(0[1-9]|[12]\d|3[01]))|((0[469]|11)(0[1-9]|[12]\d|30))|(02(0[1-9]|[1]\d|2[0-8]))))|(((\d{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[13579][26])00))0229)$

可通过网站正则表达式在线测试 | 菜鸟工具进行在线验证

JavaScript RegExp对象 几种方法

test( )   ----搜索字符串指定的值,根据结果并返回真或假

        示例: 从字符串中搜索字符"m"

var modle = new RegExp("m");
document.write(model.test("Listen, This is my home!"))    //输出结果为true,因为字符串中包含m

exec()    ---检索字符串中的指定值,返回值是被找到的值,如果没有发现匹配,则返回null

      示例:

var patt1=new RegExp("e");
document.write(patt1.exec("They want to win in this competition"));   //代码输出结果是e,因为字符串中包含e

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迷糊的小小淘

整理不易,赏点动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值