正则表达式学习

正则表达式学习


正则简介

正则表达式 (简称 regex 或者regexp)允许开发人员根据模式匹配字符串、提取子匹配信息,或简单地测试字符串是否符合该模式。

可以用来:

(1)检查一个串中是否含有符合某个规则的子串,并且可以得到这个子串;

(2)根据匹配规则对字符串进行灵活的替换操作

一、正则基础
  • 单词全写:匹配单词

    go 复制代码
    of 匹配含有of单词的内容
  • .符号 : 匹配任意字符,除了换行符

  • ^ 符号:字符串开始的地方匹配,不匹配任何字符

  • $ 符号:字符串结束的地方匹配,不匹配任何字符

  • \b :匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符

  • [字符列表]:匹配字符集

    go 复制代码
    [bdf]eer 匹配beer deer feer
    [ab5@] 匹配 "a" 或 "b" 或 "5" 或 "@"
  • [^字符列表] : 除字符集

    go 复制代码
    be[^ou]r 匹配be...r形式的内容中间不包含o,u的内容
    [^abc] 匹配 "a","b","c" 之外的任意一个字符
    [^A-F0-3] 匹配 "A"~"F","0"~"3" 之外的任意一个字符
  • [起点字符-终点字符] :字母范围

    go 复制代码
    [g-k] 匹配g-k任意字符
    [0-9] 匹配0-9任意数字,等价于 /\d/
    [f-k] 匹配 "f"~"k" 之间的任意一个字母
  • 重复: + * ?{m,n}]

    go 复制代码
    +号  :表示至少重复/出现一次,用于要标识的字符后面,相当于 {1,},比如:"a+b"可以匹配 "ab","aab","aaab".
    \*号 :表示不出现或者出现一次或者并排出现多次,相当于 {0,},比如:"\^*b"可以匹配 "b","^^^b"
    ?号  :表示可选,即可有可无,出现0次或者1次,相当于 {0,1},比如:"a[cd]?"可以匹配 "a","ac","ad"
    {n}  :表示确切出现的次数,即准确次数匹配,比如:"\w{2}" 相当于 "\w\w";"a{5}" 相当于 "aaaaa"
    {m,} :表示至少出现m次,比如:"\w\d{2,}"可以匹配 "a12","_456","M12344"
    {m,n}:表示出现次数在m和n之间【闭区间】,比如:"ba{1,3}"可以匹配 "ba"或"baa"或"baaa
  • ()号:分组,或者捕获分组

    go 复制代码
    (haa)  表示对文本中的 haa 构造分组,为了给表达式分组,我们需要将文本包裹在 () 中
    (d)(\w+) "\w+" 将匹配第一个 "d" 之后的所有字符 "xxxdxxxd"
    (d)(\w+)(d) "\w+" 将匹配第一个 "d" 和最后一个 "d" 之间的所有字符 "xxxdxxx"。虽然 "\w+" 也能够匹配上最后一个 "d",但是为了使整个表达式匹配成功,"\w+" 可以 "让出" 它本来能够匹配的最后一个 "d"
    
    (d)(\w+?) "\w+?" 将尽可能少的匹配第一个 "d" 之后的字符,结果是:"\w+?" 只匹配了一个 "x"
    (d)(\w+?)(d) 为了让整个表达式匹配成功,"\w+?" 不得不匹配 "xxx" 才可以让后边的 "d" 匹配,从而使整个表达式匹配成功。因此,结果是:"\w+?" 匹配 "xxx"
  • (?: ):非捕获分组,可以对表达式进行分组,并确保它不被引用捕获,不会存储,优化性能

    go 复制代码
    例如,如果我们想匹配一个日期格式 2019-11-10 并分别获取年、月、日,我们可以使用捕获分组来实现
    (\d{4})-(\d{2})-(\d{2})
    这将创建三个捕获分组,分别保存年、月、日的匹配结果。
    但如果我们不需要单独引用这些分组中的数据,我们可以使用非捕获分组来改写表达式:
    (?:\d{4})-(?:\d{2})-(?:\d{2})
    这样,正则表达式仍然可以匹配相同的日期格式,但不会保存匹配的年、月、日到内存中。
  • ()-\n:引用组

    go 复制代码
    反向引用 \1, \2...
    举例 1:表达式 "('|")(.*?)(\1)" 在匹配 " 'Hello', "World" " 时,匹配结果是:成功;
    匹配到的内容是:" 'Hello' "。再次匹配下一个时,可以匹配到 " "World" "。
    
    举例 2:表达式 "(\w)\1{4,}" 在匹配 "aa bbbb abcdefg ccccc 111121111 
    999999999" 时,匹配结果是:成功;匹配到的内容是 "ccccc"。再次匹配下一个时,将得到
    999999999。这个表达式要求 "\w" 范围的字符至少重复 5 次,注意与 "\w{5,}" 之间的区别
    
    举例3:
    单词 ha 和 haa 分组如下:
    ha-ha,haa-haa
    第一组用 \1 来避免重复书写。这里的 1 表示分组的顺序。请在表达式的末尾键入 \2 以引用第二组:
    (ha)-\1,(haa)-\2
  • |竖线:竖线允许一个表达式包含多个不同的分支。所有分支用 | 分隔,左右两边表达式之间 "或" 关系,匹配左边或者右边。

    go 复制代码
    下面的表达式同时匹配 cat 和 rat。请在末尾添加另一个 |,并输入 dog 以匹配所有单词。
    cat rat dog
    正则:
    (c|r)at|dog
  • \转义符:当正则使用 { } [ ] / \ + * . $^ | ? 这些特殊字符 ,为了匹配这些特殊字符本身,我们需要通过 \ 将它们转义。

    shell 复制代码
    \r 代表回车
    \n 代表换行符
    \t 代表制表符
    \\ 代表 "\" 本身
    \^ 匹配 ^ 符号本身
    \$ 匹配 $ 符号本身
    \* 匹配 * 符号本身
    \. 匹配 .$ 符号本身
    \[\] 匹配 [] 符号本身
    ...
    
    例如,要匹配文本中的 . 和 *,我们需要在它们前面添加一个 \。
    正则:
    (\*|\.)
  • ^插入符: 匹配字符串的开始

    go 复制代码
    我们用 [0-9] 查找数字,若仅查找行首的数字,请在表达式前面加上 ^
    Basic Omellette Recipe
    1. 3 eggs, beaten
    2. 1 tsp sunflower oil
    3. 1 tsp butter
    正则:
    ^[0-9]
  • $美元符号: 匹配字符串的结束

    go 复制代码
    例如在 html 的后面添加 $,来查找仅在行末出现的 html
    https://domain.com/what-is-html.html
    https://otherdomain.com/html-elements
    https://website.com/html5-features.html
    正则:
    html$
  • 单词字符 \w: 字母、数字和下划线

  • 非单词字符 \W

  • 数字字符 \d

  • 非数字字符 \D

  • 空白符 \s

  • 非空白符 \S

  • \B 匹配非单词边界,即左右两边都是 "\w" 范围或者左右两边都不是 "\w" 范围时的字符缝隙

二、正则提升
  • 零宽断言

    • 正向先行断言/正向预搜索: (?=)

      例如,我们要匹配文本中的小时值。为了只匹配后面有 PM 的数值,我们需要在表达式后面使用正向先行断言 (?=),并在括号内的 = 后面添加 PM。
      文本:Date: 4 Aug 3PM
      正则:\d+(?=PM)
      结果:3
      
    • 负向先行断言/正向预搜索: (?!)

      例如,我们要在文本中匹配除小时值以外的数字。我们需要在表达式后面使用负向先行断言 (?!),并在括号内的 ! 后面添加 PM,从而只匹配没有 PM 的数值。
      文本:Date: 4 Aug 3PM
      正则:\d+(?!PM)
      结果:4
      
    • 正向后行断言/反向预搜索: (?<=)

      例如,我们要匹配文本中的金额数。为了只匹配前面带有 $ 的数字。我们要在表达式前面使用正向后行断言 (?<=),并在括号内的 = 后面添加 \$。
      文本:Product Code: 1064 Price: $5
      正则:(?<=\$)\d+
      结果:5
      
    • 负向后行断言/反向预搜索: (?<!)

      例如,我们要在文本中匹配除价格外的数字。为了只匹配前面没有 $ 的数字,我们要在表达式前用负向后行断言 (?<!),并在括号内的 ! 后面添加 \$。
      文本:Product Code: 1064 Price: $5
      正则:/(?<!\$)\d+/g
      结果:1064
      
  • 标志/表达式属性:标志改变表达式的输出。这就是标志也称为 修饰符 的原因。标志决定表达式是否将文本视作单独的行处理,是否区分大小写,或者是否查找所有匹配项。

    • 全局标志 : /.../g:全局标志使表达式选中所有匹配项,如果不启用全局标志,那么表达式只会匹配第一个匹配项。
    • 多行标志 /.../gm:正则表达式将所有文本视作一行。但如果我们使用了多行标志,它就会单独处理每一行。
    • 忽略大小写标志/.../gmi:表达式不再大小写敏感,可以启用不区分大小写标志
  • 贪婪匹配.*:正则表达式默认执行贪婪匹配。这意味着匹配内容会尽可能长。

    它匹配任何以 r 结尾的字符串,以及前面带有该字符串的文本,但它不会在第一个 r 处停止匹配。
    文本:ber beer beeer beeeer
    正则:/.*r/
    
  • 懒惰匹配.*?:与贪婪匹配不同,懒惰匹配在第一次匹配时停止。

    在 * 之后添加 ?,将查找以 r 结尾且前面带有任意字符的第一个匹配项。这意味着本次匹配将会在第一个字母 r 处停止。
    文本:ber beer beeer beeeer
    正则:/.*?r/
    
三、使用案例
  • 示例:^.{m,n}$

    匹配固定长度内容:^.{n}$,匹配任意开头但是长度n的内容
    匹配最小长度内容:^.{m,}$,匹配任意开头但是长度不低于m的内容
    匹配区间长度内容:^.{m,n}$,匹配任意开头但是长度在[m,n]之间的内容
    
  • 示例:.*匹配

    在正则表达式的末尾添加 .* 来匹配以 how to write 开头的表达式,并匹配后面的所有内容。
    正则1:^how to write
    正则2:how to write.*
    
    在两个 .* 之间写上我们要查找的字段,以匹配包含该字段的所有的内容。例如匹配包含buy的内容
    正则:.*buy.*
    
    在.*\.和$之间加入想要作为结尾的字段,可以匹配以.XX格式结尾的内容,例如匹配.html文件
    正则:.*\.html$
    
  • 匹配http、https

    匹配http或者https
    正则1:^http 或者 ^(http|https)【仅作为开头】
    正则2:http.*【不限于开头】
    
    匹配非https即只要http
    正则:http[^s].*
    
    URL:^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
    
  • 域名

    域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?
    
  • 邮箱Email

    Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
    
  • 手机号

    手机号码:^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$
    
    电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"等格式):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
    
    国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
    
  • 身份证

    身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X:(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)
    
  • 密码

    强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$
    强密码(必须包含大小写字母和数字的组合,可以使用特殊字符,长度8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
    
  • QQ号

    腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
    
  • 邮政编码

    中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
    
  • Ipv4地址

    IPv4地址:((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}
    
  • 其他

    空白行的正则表达式:\n\s*\r (可以用来删除空白行)
    HTML标记的正则表达式:<(\S*?)[^>]*>.*?|<.*? /> 
    首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等))
    
四、附录
相关推荐
幽兰的天空4 小时前
【Python】正则表达式
python·正则表达式
dawn1912284 小时前
Java 中的正则表达式详解
java·开发语言·算法·正则表达式·1024程序员节
MarkHD2 天前
第七天 正则表达式
正则表达式
史努比的大头3 天前
正则表达式基础知识
正则表达式
Katherine10293 天前
正则表达式笔记
笔记·正则表达式·1024程序员节
IT猫咪酱3 天前
【mysql】转义字符反斜杠,正则表达式
正则表达式
阿智智3 天前
正则表达式使用举例一(Python下)
python·正则表达式·re包
炫彩@之星4 天前
Sublime Text3快捷键大全--正则表达式元字符-详细说明
网络安全·正则表达式·sublime text·安全测试
l23456789o4 天前
java使用正则表达式校验字符串pwd,是否符合包含大写小写数字特殊字符长度超过8位
java·开发语言·正则表达式