关于正则表达式的一些笔记

来源:互联网 发布:淘宝拍摄摄影棚的搭建 编辑:程序博客网 时间:2024/06/05 07:26
常用的元字符:
 -    .      匹配除换行符以外的任意字符
 -    \w  匹配字母、数字、下划线、汉字
 -    \s    匹配任意的空白符
 -    \d    匹配数字
 -    \b    匹配单词的开始或结束(单次当中总不能出现换行之类)
 -    ^    匹配字符串的开始
 -    $    匹配字符串的结束

所有表示元字符匹配个数的元字符(数量一般出现在需要控制字符的右边)
 -    *    重复零次或更多次
 -    +    重复至少一次或更多次
 -    ?    重复零次或一次
 -    {n}    重复n次
 -    {n,m}    重复n到m次
 -    {n,}    重复n次或更多次

如果希望匹配一定范围内的字符,只需要在方框中将其列出
 -    [0-9] 与 \d 的含义是一样的
 -    [a-z0-9A-Z] 与 \w的含义是一样的
 -    [,!?] 匹配三个标点符号 , ! ? (中括号中出现的字符不需要转义)
 
例如:要匹配和(010)1234567或者010-1234567的正则表达式是:^\(?0\d{2}\[)-]\d{7}$
当然,上面的正则表达式可能会匹配出010)1234567或者(010-1234567这样的不符合预期结果的字符串
这就需要使用到分支结构

分支结构:
| 表示分支结构(就是逻辑短路或的运算符,从左只有匹配测试,左边的通过了右边的就不测试了)
上面的正则表达式就可以写成:^\(0d{2}\)d{7}$|^0d{2}-d{7}$

分组结构:
如果重复一个数字是\d{n},那么重复一组制定的数字呢,要使用分组结构比如(213){3}会匹配到含有“213213213”的内容
现在需要对一个输入的ip地址检查其合法性:^(\d{3}\.)\d{3}$,但是这可能出现例如256.333.444.555这样可怕的ip
但是很遗憾正则表达式并不支持数学运算匹配,只好这么写:^(2[0-4]\d|25[0-5]|[01]?\d\d?\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$
分析:ip每一段由一个“三位数组成”,有三种情况:
    - 2 , [0-4] , [0-9]        (以2开头,第二位不能超过4,第三位任意数字)
    - 2 , 5 , [0-5]                (以2开头,第二位是5,第三位不能超过5)
    - [01]?,[0-9]?,[0-9]?    (第一位是01当中的一个或者什么都没有,后两位随意)(注意:这里至少要保证有一个数字存在)

反义机制:
将元字符大写比如存在数字\d,反之不存在数字\D
[]的用法:存在ab当中任意一个的字符串:^[ab]$,ab当中任何一个都不存在的字符串^[^ab]$(只要不包含ab都能够表达)

后向引用:
所有被( )括在当中的表达式都将是一个独立的分组,从左向右,从1到n(n表示任意数字),依次被标记,使用例如\1将其引用
比如^(\w\w)\d\1$能够匹配 go2go ha6ha的字符串

零宽断言:
(?=exp) 零宽正预测先行断言:断言某内容后一定有exp紧跟其后(不包括exp)
(?=<exp) 零宽正回顾后发断言:断言某内容一定紧跟在exp之后(不包括exp)(真TM不是地球人起的名字)
例如 被空格隔开的任意数字的正则表达式为:^(?=<\s)\d+(?=\s)$

(?!exp) 零宽负预测先行断言:断言某内容后一定没有exp紧跟其后
(?<!exp) 零宽负预测后发断言:断言某内容一定没有跟随在exp之后

正则表达式当中的注释:(#comment)

贪婪与懒惰:
正则表达式的匹配规则默认是贪婪的:
例如用^a.*b$去匹配字符aabab,得到的匹配项是aabab,也就是说尽量多的去匹配。那如果我们希望匹配到aab和ab要怎么办:
使用懒惰规则:即在表达匹配字符数量的元字符后面加上一个
比如上面的例子可以这么写:^a.*?b$得到的匹配项是aab和ab

 
平衡组、递归匹配
当需要对多层嵌套的左右括号作匹配时,使用分支结构考虑种种情况是不可能,这个时候就需要用的一种叫做平衡组的方法
平衡组主要是利用了堆栈的概念,先进后出,从左向右对左括号做压栈操作,对右括号做出栈操作,每次检查判断堆栈中是否还有能够出栈的元素
检查结束时判断堆栈中是否还有元素未出栈。
 
需要实现定义一个‘栈’-‘group’,通过(?'group'\()对(压栈,(?'-group'\()对(出栈
最后判断group当中是否还有内容,如果还有内容说明匹配不成功 - (?(group)(?!))
对这个判断的说明:(?(group)yes|no)判断group是否还有内容有则执行yes,没有则执行no
所以上述问题可以这样写:
\(                                              #最外层的左括号
    [^()]*                                   #其后跟随非括号任意内容
    (
        (
            (?'group'\()[^()]*        #遇见左括号压栈
        ) + 
        (
            (?'-group'\))[^()]*      # 遇见右括号弹栈
        ) +
    ) *
    (?(group)(?!))                      #判断堆栈是否为空
\)                                             #最外层的右括号

原创粉丝点击