美文网首页程序员互联网
从零开始学习正则表达式

从零开始学习正则表达式

作者: _誌念 | 来源:发表于2017-11-22 16:09 被阅读88次

    正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表通常被用来检索、替换那些符合某个模式(规则)的文本。

    参考文章《正则表达式30分钟入门教程》

    基本语法

    1.元字符

    字符 描述
    . 匹配除换行符以外的任意字符
    \w 匹配字母或数字或下划线或汉字
    \s 匹配任意的空白符,包括空格,制表符(Tab),换行符
    \d 匹配数字,(0,1,2,3....)
    \b 匹配单词的开始或结束
    ^ 匹配字符串的开始
    $ 匹配字符串的结束

    下面看几个例子👇

    1. 匹配已字母a开头的单词,先匹配某个单词的开始处(\b),然后是字母a,然后是任意的字母或数字或下划线或汉字,最后是单词结束处。
    \ba\w*\b
    
    1. 匹配5位到12位数字
    \d{5,12}      //只能保证字符串中包含5到12位连续的数字,不能保证整个字符串就是5到12位数字。
    
    ^\d{5,12}$    //整个字符串必须是5到12个数字。
    

    2.字符转义

    如果你想查找元字符本身的话,比如查找.或者*,就出现了问题,你没办法指定他们,因为他们会被解释成别的意思,这时可以使用\来取消这些字符的特殊含义。因此应该使用\.\*,如果要查找\本身,也需要用\\

    regtext\.py 匹配 regtext.py
    c:\\windows 匹配 c:\windows
    

    3.重复

    字符 描述
    * 重复零次或多次
    + 重复一次或多次
    ? 重复零次或一次
    {n} 重复n次
    {n,} 重复n次或更多次
    {n,m} 重复n到m次
    Windows\d+  //Windows后面跟一个或多个数字
    \d{5,12}    //匹配5到12个数字
    

    4.字符类

    要想查找字母,数字或者空白是很简单的,因为已经有了对应的元字符,如果你想匹配没有预定义元字符的字符集合,很简单只要在方括号里列出他们就行了。

    [aeiou]   //匹配任意一个英文元音字母
    [.?!]     //匹配标点符号.或者?或者!
    [0-9]     //匹配0到9之间的任意数字,含义同\d
    

    下面看一个复杂的表达式:

    \(?0\d{2}[) -]?\d{8}
    

    首先分析上面表达式的含义,()也是元字符,所以这里需要转义。
    首先是一个(出现0次或者一次,然后是一个0,然后是两个数字,然后是)或者空格或者-中的零个或一个,最后是8个数字。能匹配到类似下面这种的字符串(011)12345678,011-12345678

    5.分支条件

    不幸的是上面那个正则也能匹配到(011-12345678等不正确的格式,要解决这个问题需要用到分支条件,如果满足其中任意一种规则都应该当成匹配,具体方法用|隔开。

    0\d{2}-\d{8}|0\d{3}-\d{7}     //匹配3位区号,8位本地号,或者4位区号,7位本地号。
    \(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}  //匹配3位区号的电话号码,区号可以有小括号也可以没有,区号和本地号之间可以有空格,连接符,也可以没有
    

    6.分组

    我们已经提到了怎么重复单个字符 (直接在字符后面加上限定符就行了),但是如果想要重复多个字符又该怎么办,你可以用小括号来指定子表达式(也叫分组),然后你就可以指定这个子表达式的重复次数了,也可以对子表达式进行一些其他的操作。

    (\d{1,3}\.){3}\d{1,3}
    

    上面表达式的含义是:\d{1,3}匹配1到3位数字,(\d{1,3}\.){3}匹配1到3位数字加一个英文句号(这个整体也就是这个分组)重复3次,\d{1,3}最后加一个1到3位的数字。

    7.反义

    有时候需要查找不属于某个能简单定义的字符类的字符,比如想查找除了数字以外,其他任意字符都行的情况下,这时需要用到反义。

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

    8.后向引用

    默认情况下,每个分组会自动拥有一个组号,规则是:从左到右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,依次类推。
    后向引用用于重复搜索前面某个分组匹配的文本。例如\1代表分组1匹配的文本。

    \b(\w+)\b\s+\1\b
    

    可以用来匹配重复的单词,像go go,或者kitty kitty,\b(\w+)\b表示在单词的开始和结束之间有一个或多个字母,数字,下划线或汉字,这个单词会被捕获到编号为1的分组中,然后是一个或多个空白字符\s+,最后是分组1中捕获的内容(也就是前面匹配的那个单词)\1

    \b(?<word>\w+)\b\s+\k<word>\b
    

    可以自己指定表达式的组名,要指定一个子表达式的组名,可以使用(?<word>\w+)或者(?'word'\w+)

    常用的分组语法:

    分类 语法 说明
    捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
    (?exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
    (?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
    零宽断言 (?=exp) 匹配exp前面的位置
    (?<=exp) 匹配exp后面的位置
    (?!exp) 匹配后面跟的不是exp的位置
    (?<!exp) 匹配前面不是exp的位置

    9.断言

    👇通过几个例子进行学习:

    1. 匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you are dancing.,他会匹配singdance
    \b\w+(?=ing\b)
    
    1. 匹配已re开头的后半部分(除了re以外的部分),如查找reading a book,会匹配到ading
    (?<=\bre)\w+\b
    
    1. 匹配这样的单词,它里面出现了字母q,但q后面跟的不是字母u,(?!u)它只匹配一个位置,并不消费任何字符。
    \b\w*q(?!u)\w*\b
    
    1. 匹配三位数字,并且这三位数字的后面不能是数字
    \d{3}(?!\d)
    
    1. 匹配前面不是小写字母的7位数字
    (?<![a-z])\d{7}
    

    10.贪婪匹配

    当正则表达式中包含能接受重复的限定符时,通常的行为是匹配尽可能多的字符,例如a.*b它会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab,它会匹配整个字符串aabab。这被称为贪婪匹配。

    字符 描述
    *? 重复零次或多次 ,但尽可能少重复
    +? 重复一次或多次,但尽可能少重复
    ?? 重复零次或一次,但尽可能少重复
    {n}? 重复n次,但尽可能少重复
    {n,m}? 重复n到m次,但尽可能少重复
    a.*?b
    

    匹配最短的,以a开始,以b结束的字符串,如果匹配aabab会匹配为aabab
    到这里,基本的语法已经讲解完了。

    实用例子

    1.匹配IP地址

    匹配IP地址之前,需要首先知道IP地址的格式,IP地址分为4个字段 (IP地址每个字段都在0-255之间),例如:192.168.0.0。所以我们的重点就是控制4个字段都在0-255之间。
    每个字段至少有一位,通俗的写法是这样\d|\d\d|[01]\d\d|2[0-4]\d|25[0-5],将其简化后为\[01]?\d\d?|2[0-4]\d|25[0-5],注意第一个分支中使用\d\d?而不使用\d?\d,如果根本不存在数字,会更快的报告匹配失败,所以最后的正则表达式为:

    ^([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$
    
    匹配IP地址.png
    2.验证用户名和密码

    由数字和字母组成6-12,则不能为纯数字和纯字母组成的,(?![0-9]+$)表示不能是纯数字,(?![a-zA-Z]$)表示不能是纯字母。

    ^(?![0-9]+$)(?![a-zA-Z]$)[0-9a-zA-Z]{6,12}$
    
    匹配用户名和密码.png
    3.匹配对称的括号

    匹配[呵呵],[微笑]这类表情时会用到这种匹配,首先对[进行转义为\[,然后是一个分组([^ \[]*?),表示匹配除空格和[以外的字符,重复零次或多次,但尽可能少重复,最后匹配]

    \[([^ \[]*?)]
    
    匹配表情.png
    4.匹配微博@符号

    只允许 英文数字下划线连字符,和 unicode 4E00~9FA5 范围内的中文字符

    @[-_a-zA-Z0-9\u4E00-\u9FA5]+
    
    匹配@.png
    5.匹配电话号码

    匹配字符串中出现的所有的电话号码,正则表达式如下:

    1[3578][0-9]{9}
    
    匹配手机号.png
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: @"1[3578][0-9]{9}" options:kNilOptions error:NULL];
    NSArray<NSTextCheckingResult *> *phoneResult = [regex matchesInString:text.string options:kNilOptions range:text.yy_rangeOfAll];
    for (NSTextCheckingResult *phone in phoneResult) {
         if (phone.range.location == NSNotFound && phone.range.length <= 1) continue;
            NSLog(@"%@",[text.string substringWithRange:phone.range])
      }
    

    正则表达式可视化网址Regexper

    相关文章

      网友评论

        本文标题:从零开始学习正则表达式

        本文链接:https://www.haomeiwen.com/subject/byjvvxtx.html