zoukankan      html  css  js  c++  java
  • 我眼里的正则表达式(入门)

    正则对于新人来说是一个头疼的名字,让人闻而生畏。但是,在我看来,正则,并没有那么神秘。

    接触正则应该有三年不止了吧,我也不知道自己怎么就走过了畏惧正则的时期,而且在一个小圈子里面还成了正则强人。

    今天就基于我对正则的理解,简单描述一下我眼里的正则,希望能够解除正则新人对于正则的畏惧感。

    先概括一下,正则三段论:

    定锚点,去噪点,取数据

    1、入门:正则字符

    关于正则字符,很多文章都会讲到,足足有一篇文章才能描述清楚,我这里就不多说,对于我,平时,常用的有:

    1. . 匹配不包括换行的任意字符,在php的s修饰符下面可以匹配换行,如$pattern='#<div>(.*?)</div>#s';就可以匹配div内容有换行的数据。

    2. s 空格、tab

    3. * 匹配零个或更多个,即0~n

    4. + 匹配一个或更多个,即至少一个,1~n

    5. 转义
      一个特殊字符前加就表示转义,说明把它当普通字符用

    6. [] 单字符取一个,比如[abc]会匹配a或b或c

      但是,如果[]里面加上^则会变成排除这个字符,如[^abc]就表示不是a、不是b、也不是c
      另外,在[]里面可以使用-表示一个范围,如[0-9]表示从0到9,类似的还有[a-zA-Z],如果要包含-字符,可以给它加上转义[-]
      关于[]常见的错误用法是:[ab|bc]用来表示abbc,实际上,它得到的结果是[abc|],即a或b或c或|这4个字符(单字符)的任意一个。这里可以改成(ab|bc)
      总结:[]里面的特殊符有五个:[]-^,其他字符都是普通字符,包括*.?等。
      说明:

      • ^[^ 的首位时候才有特殊意义
      • [0-9 -在不是首尾的时候有特殊意义
      • [ ] 因为占用[] 本身字符,所以有特殊意义
      • 本身是转义符,有特殊意义
    7. ^ 字符串开始
      这里的^跟[]里面用的^是同一个字符,但是却不是一个意思,这里它表示整个字符串的开始,比如^www表示以www开头的字符串,注意区分,不在[]里面的是开始符,在里面的排除

    8. $ 字符串结束

    9. {1,3} 循环次数
      [0-9]{1,3}表示在0-9的范围里面循环1个、2个或者3个,可能结果有5、20、415等。
      如果循环指定次数,如3次,则{3,3}可以简写成{3}
      如果刚好需要匹配字符{1},则正则需要给{进行转义,得到{1}的正则。
      如果{}中间不是数字,则{}本身不需要转义。

    10. ? 有两个用法
      (1) 匹配一个或零个,比如https?匹配的https(一个s)或者http(零个s)
      (2)非贪婪模式
      所谓非贪婪模式,就是匹配尽可能少的内容,比如,对于源字符串

    <div>a</div><div>b</div>
    

    使用<div>(.*?)</div>会得到2个结果(注意:如果源字符串有换行,使用[sS]替换 . ):

    <div>a</div>
    

    <div>b</div>
    

    因为,当遇到第一个</div>,非贪婪模式就不会再往后找了。
    而使用<div>(.*)</div>(贪婪模式)则会得到整个字符串

    <div>a</div><div>b</div>
    

    ,因为它会匹配所有字符直到后面再找不到</div>

    1. | 多个数据选一(常用于多字符)
      前面提到[]里面的字符有选一个字符功能,但是假如不是一个字符,比如:http|ftp|svn 就需要用|分开,|的作用域是一直往后直到遇到括号,比如,对于源字符串
    http abc
    ftp abc
    svn abc
    

    http|ftp|svn abc匹配的结果是:

    http
    

    ftp
    

    svn abc
    

    想要匹配 http abcftp abcsvn abc就要使用括号把前边的协议括起来,如(http|ftp|svn) abc 可以得到预期的结果。

    1. () 数据分界和取数据
      上面例子(http|ftp|svn) abc就是数据分界的例子,然后,匹配结果会得到一个1的子集数据,这里就是子模式的概念,利用子模式,可以得到想要取出来的数据。子模式1、2、3的计算方法为左括号的计数,从左到右,从1开始,比如:
      (http|ftp|svn)://([^/]+)1得到的是(http|ftp|svn)里面的数据,[2]得到([^/]+)里面的数据,对于嵌套括号也是点左括号即可。

    2. (?:) 非捕获组
      上面说到()作为子模式可以得到它里面的数据,但是,有些时候,()只是作为数据分界功能,并不需要取出来,这时候就要用到非捕获组的概念了。比如:(http|ftp|svn)://([^/]+)只想得到域名,也就是[2],那么(http|ftp|svn)就只是数据分界的功能,这里不需要捕获,因此使用非捕获组功能,(?:http|ftp|svn)屏蔽这部分的数据获取,此时,(?:这个左括号排除1计数,也就是(?:http|ftp|svn)://([^/]+)中的([^/]+)变成1了。


    关于常用字符的使用差不多到这里,还有更多的请参考正则表达式30分钟入门教程,这是我看过比较全面的正则入门资料。

    2、 操作:定锚点

    每一个正则都是有针对性的,只有这样正则才有意义。因此,写正则之前,先观察你要解析的数据,找准唯一的锚点,比如,你要解析一个页面的title标签,得到title内容,那么这个title就是锚点。有时候,所要取的数据确实无法定位一个唯一的锚点,那么,你可以分解数据,先通过一个唯一锚点锁定你的数据块,取出来之后,再对这个数据块取数据即可。比如,有这么一段源字符串:

    <div id="module_1">
        <div class="content">
                  content 1
        </div>
    </div>
    <div id="module_2">
        <div class="content">
                  content 2
        </div>
    </div>
    

    你直接通过class="content"来匹配数据的话很明显会得到两个,那么,你可以扩展它的数据域,先以id="module_1"作为锚点,获取整个

    <div id="module_1">
        <div class="content">
                  content 1
        </div>
    </div>
    

    然后在对这个数据块的数据处理,得到class="contents"的内容即可。
    因此,这里用到2个正则:

    (1)<div id="module_1">(.*?)</div>s*<div id="module_2">
    (2)<div class="content">(.*?)</div>

    总结:锚点,就是能唯一定位你数据的标识

    3、 操作:去噪点

    所谓去噪点,就是把无关的东西都当浮云,用通配符过掉它,只关心我们想要的数据,比如:
    <meta content="text/html; charset=utf-8" http-equiv="content-type">
    要从这里得到字符集utf-8,我们需要怎么做?
    首先,定位锚点,有<metacharset=和utf-8后面的",其他都是浮云~
    因此得到正则:
    <meta[^>]*charset=([^"]+)"
    即可,用子模式取数据[1]就能得到utf-8

    总结:关心的留下,不关心的都是浮云

    4、 操作:取数据

    关于取数据,上面一大篇下来大家应该有概念了,就是利用子模式来获取,这里不再赘述。

    总结:子模式计数,数左括号从1开始,排除非捕获组的左括号

    最后,希望大家有一个愉悦的正则之旅,你一定会爱上她的,跟我一样。: )

    原文发表自Zjmainstay学习笔记 我眼里的正则表达式

  • 相关阅读:
    【提高组】
    【学习】数论
    【2019.10.2】NOIP2018 模拟赛
    【普及组BOSS】
    ELK搭建elasticsearch常见报错
    Linux 下 安装Python第三方模块工具箱pip,以及用pip安装的方法
    Centos 基本命令不能用恢复方法
    Docker0 网卡删除
    Tomcat 设置开机自启
    Python 终端输出字体颜色
  • 原文地址:https://www.cnblogs.com/Zjmainstay/p/my-regexp.html
Copyright © 2011-2022 走看看