• 正则入门实例拓展


    本篇主要介绍Perl(以及其他流派的正则)提供的简记法(shorthands),以及修改文本中使用的正则环视特性,包括几个举例。在看这篇之前,不管你是否精通正则,建议首先看下这篇《正则基础与细节回顾》,因为强大的正则里面,需要关注的细节太多了。

    1.常用空白和任意字符匹配


    s[ ]*: 匹配空白
    .*: 匹配任何字符. .号通配符,*任意个数,可以为零。

    2.Perl(以及其他流派的正则)提供的简记法(shorthands):


    : 单词分界符
    : 制表符
    : 换行符
    : 回车符
    s: 匹配任何空白符 (space, tab, newline, formfeed, and such)
    S: 除s之外任何字符
    w: 相当于[a-zA-Z0-9_]
    W: 除w之外任何字符,相当于[ˆa-zA-Z0-9_]
    d: 相当于[0-9]
    D: 除d之外任何字符,相当于[ˆ0-9]"

    3.使用正则修改文本


    3.1捕获


    Perl可以使用$1,$2,$3之类的变量来保存相对应的(···)括号内的子表达式匹配的文本。子表达式的编号按照开括号出现的先后顺序,从1开始,子表达式可以嵌套,比如(Washington( DC)?)。我们修改文本,可能会保留某些原文本,那么使用$1这类的变量就可以实现。简单的举一个例子,比如说我们想给所有的数字加上双引号,我们可以使用(d)+匹配到所有的数字后,替换结果用"$1"取代,最终到达我们想要的效果。


    (?:···)这种写法可以用来分组文本,但是并不捕获。(···)当然也可以分组,但是副作用就是他们捕获的文本依然会保存在特殊的变量中。比如(Ad)+,我们只是想让字母A和一个数字组合起来,但是这样正则依旧会捕获到括号中的内容并且记录,虽然看似没有多大影响,但是对于文本量比较大的文件,为了增加匹配效率,我们可以使用(?:Ad)+,这个时候再用类似$1这样的变量,就获取不到引用的文本了。

    3.2环视(lookaround)


    我们先来想一个问题,假如我们有诸如3567657745这样一批代表数量的数字,一般为了方便,我们会这样写3,567,657,745。为了解决这个问题,我们首先想到的是从右向左每隔3个数字加个逗号,并且逗号前面必须有数字,但是正则一般都是从左向右工作的。那么接下来我们就介绍正则的环视特性。

    首先强调的是,环视不匹配任何字符,只匹配文中的特定位置,这一点和单词分解符、锚点^$相似。但是,环视更加通用。

    环视有四种类型,参考以下表格

    类型 正则表达式 匹配成功的条件...
    肯定顺序环视 (?=···) 子表达式能匹配右侧文本
    否定顺序环视 (?!···) 子表达式不能匹配右侧文本
    肯定逆序环视 (?<=···) 子表达式能匹配左侧文本
    肯定逆序环视 (?<!···) 子表达式不能匹配左侧文本

    了解这些后,我们继续回到给数字加逗号的问题,首先思考3的倍数,3的倍数很好处理,直接(ddd)+$,加上$来保证数字后面不存在其他字符。,在左边是数字,我们可以使用(?<=d)来限定匹配的位置,于是整个正则表达式就是(?<=d)(?=(ddd)+$)。其实这样子还是不太好,因为里面存在括号,括号中的内容会被特定的变量&1等引用,所以我们最好使用只是分组的(?:···)来处理一下,于是变成了(?<=d)(?=(?:ddd)+$),猛一看上去有点难以理解,但是一步一步看,还是挺清晰的。我们已经知道,环视不会匹配任何字符,只是匹配位置,匹配到这样的位置后,我们只要插入一个逗号即可,于是替换文本只需要是,就可以了,我们看下处理前后的效果。


    掌握了环视,我们回头来想一下这个单词分界符,如果单词分解符的意思是,一侧是w,另外一侧不是w,那么我们就可以用(?<!w)(?=w)来表示单词的起始分解符,用(?<=w)(?!w)来表示单词的结束分界符,那么两则结合起来,(?<!w)(?=w)|(?<=w)(?!w)就等价于。当然如果语言本身支持就不要多此一举了,简洁效率又高。

    补充一点,刚才我们给数字加逗点中,保证了结尾不是其他字符,那么像23456323s是匹配不到的,使用了$,千万要理解清楚,去掉$后将会是这样子,图片中匹配到的灰色位置。

    为了匹配23456323s,其实这里只需要结尾不是数字就可以了。我们使用简记法d来匹配数字,那么尾部不是数字就可以使用(?!d)来表示了,所以最终的正则可以这样写(?<=d)(?=(?:ddd)+(?!d))

    这里强调一点,非数字,我们可能会想到DD的意思是,“匹配一个不是数字的字符”,而这个字符是必须的,假如正好处于行尾,没有任何字符,是匹配不到的。上一篇中我们已经强调过这一点。

    环视类型中,顺序和逆序所获取的支持十分有限(使用也不广泛),顺序比逆序早出现几年,尽管Perl支持两着,其他语言就难说了,所以接下来我们不使用逆序环视来解决给数值添加逗号问题。(d)(?=(?:ddd)+(?!d))左侧使用捕获型括号,替换文本只需要在逗号前面加上$1即可,也就是$1,,同样到达了我们预期的效果。

    更多实例,可以参考《Mastering Regular Expressions》第三版,里面使用Perl语言,举了诸多实例,有兴趣的朋友可以参考下,当然也可以参考中文翻译版本《精通正则表达式》。希望本篇文章可以帮组你更好的掌握正则。

  • 相关阅读:
    HDU 5912 Fraction (模拟)
    CodeForces 722C Destroying Array (并查集)
    CodeForces 722B Verse Pattern (水题)
    CodeForces 722A Broken Clock (水题)
    CodeForces 723D Lakes in Berland (dfs搜索)
    CodeForces 723C Polycarp at the Radio (题意题+暴力)
    CodeForces 723B Text Document Analysis (水题模拟)
    CodeForces 723A The New Year: Meeting Friends (水题)
    hdu 1258
    hdu 2266 dfs+1258
  • 原文地址:https://www.cnblogs.com/chao8888/p/8352476.html
Copyright © 2020-2023  润新知