正则表达式

正则表达式就是记录文本规则的代码。只不过比起通配符,它能更精确地描述你的需求

1、元字符

常用的元字符

    代码  说明
    .   匹配除换行符以外的任意字符
    \w  匹配字母或数字或下划线或汉字,,等价于[a-z0-9A-Z_](如果只考虑英文的话)
    \s  匹配任意的空白符
    \d  匹配数字,等价于[0-9]
    \b  匹配单词的开始或结束
    ^   匹配字符串的开始
    $  匹配字符串的结束

2、重复(限定符)
常用的限定符

    代码/语法   说明
    *   重复零次或更多次,任意数量的不包含换行的字符
    +   重复一次或更多次
    ?   重复零次或一次
    {n} 重复n次
    {n,}    重复n次或更多次
    {n,m}   重复n到m次

懒惰限定符

    代码/语法   说明
    *?  重复任意次,但尽可能少重复
    +?  重复1次或更多次,但尽可能少重复
    ??  重复0次或1次,但尽可能少重复
    {n,m}?  重复n到m次,但尽可能少重复
    {n,}?   重复n次以上,但尽可能少重复

例子

    1、精确地查找hi这个单词
       \bhi\b
    2、先是单词hi,然后是任意个任意字符(但不能是换行),最后是Lucy这个单词
       \bhi\b.*\bLucy\b
    3、以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字
       0\d{2}-\d{8}   \d必须连续重复匹配2次(8次)
    4、匹配刚好6个字符的单词
      \b\w{6}\b
    5、QQ号必须为5位到12位数字
      \d{5,12}\d
    6、匹配最长的以a开始,以b结束的字符串,称为贪婪匹配。
      a.*b
    7、匹配最短的,以a开始,以b结束的字符串
      a.*?b
   8、
       \(?0\d{2}[) -]?\d{8}
    解析:首先是一个转义字符\(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)或-或空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。
    匹配到不符合的:(012-90998908或者010)19092345

    修改
    \(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}
  9、
  [a-z]是指小写字母中的一个字符
  [A-Z]是指大写字母中的一个字符
  [0-9]是指数字中的一个字符
  [a-zA-Z0-9_-]是指大小写字母、数字、下划线、横线中的一个字符
  [a-z][A-Z][0-9]是指三个字符,其中第一个是小写字母,第二个是大写字母,第三个是数字

3、字符转义
  \ 取消元字符的特殊意义

要查找\本身,用\\
要查找*本身,用\*
要查找(本身,用\(

4、反义:查找不属于某个能简单定义的字符类的字符

常用的反义代码

代码/语法   说明
\W  匹配任意不是字母,数字,下划线,汉字的字符
\S  匹配任意不是空白符的字符
\D  匹配任意非数字的字符
\B  匹配不是单词开头或结束的位置
[^x]    匹配除了x以外的任意字符
[^aeiou]    匹配除了aeiou这几个字母以外的任意字符

例子:

 匹配用尖括号括起来的以a开头的字符串
  <a[^>]+>
 注意:<a+>会匹配到<aaa>like>

5、分枝条件
满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开,从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了,注意顺序

美国邮编的规则是5位数字,或者用连字号间隔的9位数字
\d{5}-\d{4}|\d{5}
只会匹配5位的邮编(以及9位邮编的前5位)
\d{5}|\d{5}-\d{4}

6、分组
重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作
默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。

常用分组语法
    分类      代码/语法       说明
    捕获      (exp)           匹配exp,并捕获文本到自动命名的组里
                (?<name>exp)    匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
                (?:exp)         匹配exp,不捕获匹配的文本,也不给此分组分配组号
    零宽断言    (?=exp)         匹配exp前面的位置
                (?<=exp)        匹配exp后面的位置
                (?!exp)         匹配后面跟的不是exp的位置
                (?<!exp)        匹配前面不是exp的位置
    注释      (?#comment)     这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读
简单的IP地址匹配
(\d{1,3}\.){3}\d{1,3}
分析:\d{1,3}匹配1到3位的数字,(\d{1,3}\.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})。匹配到不符合的260.333.222.999

使用冗长的分组
描述一个正确的IP地址:255.255.255.255
((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
25[0-5] 代表250~255范围
2[0-4]\d  代表240~249范围
[01]\d\d? 代表0~9或10~19或100~199的范围
语法(?#comment)来包含注释。例如:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)。

7、反向引用
后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本

匹配重复的单词,像go go
\b(\w+)\b\s+\1\b

指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?<Word>\w+)(或者把尖括号换成'也行:(?'Word'\w+))

反向引用这个分组捕获的内容,你可以使用\k

匹配重复的单词,像go go
\b(?<Word>\w+)\b\s+\k<Word>\b。

8、零宽断言
用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言

(?=exp) 匹配exp前面的位置
(?<=exp)    匹配exp后面的位置

匹配以'a'间隔的数字(再次强调,不包括'a'字符)
匹配a字母前面两个数字
\d+(?=\a)

9、负向零宽断言
查找不是某个字符或不在某个字符类里的字符的方法(反义)。但是如果我们只是想要确保某个字符没有出现

(?!exp) 匹配后面跟的不是exp的位置
(?<!exp)    匹配前面不是exp的位置

\b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的单词。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为[^u]总要匹配一个字符,所以如果q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w*\b将会匹配下一个单词,于是\b\w*q[^u]\w*\b就能匹配整个Iraq fighting。负向零宽断言能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:\b\w*q(?!u)\w*\b。


匹配除a字母外前面两个数字,如11b,22c等 
\d{2}(?!a)

补充:

(?:exp) 非捕获组,匹配exp的内容,但不捕获到组里

至于作用,一般来说是为了节省资源,提高效率

比如说验证输入是否为整数,可以这样写
^([1-9][0-9]*|0)$
这时候我们需要用到()来限制“|”表示“或”关系的范围,但我们只是要判断规则,没必要把exp匹配的内容保存到组里,这时就可以用非捕获组了
^(?:[1-9][0-9]*|0)$

以上只是一个简单的例子,或许会觉得无所谓,但是如下的日期正则,如果全都用捕获组,那就是对资源的极大浪费了

^(?:(?:(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))([-/.])(?:0?2\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\d)?\d{2})([-/.])(?:(?:(?:0?[13578]|1[02])\2(?:31))|(?:(?:0?[13-9]|1[0-2])\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\2(?:0?[1-9]|1\d|2[0-8]))))$

参考:
http://www.jb51.net/tools/zhengze.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值