前言

无论你是出于什么原因需要掌握正则表达式(诸如爬虫、文本检索、后端服务开发或Linux脚本),如果之前从没接触过正则表达式(比如我)很容易在如山般的公式中迷失,以至于你在项目写的正则表达式很可能会因为组织混乱而被后来的开发者吐槽。

正则表达式Regular Expression本质上是一种文本模式,包括普通字符和特殊字符(也被称为元字符),使用一个字符串表达式来匹配符合该规则的字符串。

学习工具:正则表达式可视化工具

https://jex.im/regulex/#!flags=&re=^(a|b)*%3F%24

这个网站可以可以用可视化的方式展示正则表达式的匹配模式,比如^[0-9]+abc$表示从字符串的开头开始匹配一或多个数字,然后以abc结尾。

https://regexr.com/

这个网站可以用于测试你写的正则表达式匹配效果,比如Re(\w)+表示匹配以Re开头的字符串。

从通配符讲到正则表达式

在操作系统上或者SQL中我们经常接触到通配符的使用,比如模糊搜索文件(比如*.dat表示匹配所有以.dat为后缀的文件)。常用的通配符包括:

  • ?:匹配0或者1个任意字符
  • *:匹配0或者多个任意字符

上面这两个通配符尽管用途很广,但很难穷尽任意字符串匹配的场景,正则表达式的功能更加强大,足以覆盖字符串匹配的大部分场景。上面网站展示的两个例子已经说明其的强大之处,接下来我们只需要掌握它的语法即可。

正则表达式最常用的几个用途包括:

  • 字符串模式校验:比如我们后端的http服务受到参数时校验该字符串是否是日期、电话和身份证等
  • 文本批量替换:可以对满足匹配的规则的文本进行全部替换
  • 从字符串中提取子字符串:比如在爬虫的时候从整个html页面中提取需要的子字符串
  • 检查一个字符串中是否包含某个类型的字符串

正则表达式语法

普通字符包括没有被显式指定为元字符的所有可打印和非打印字符,包括所有的大写和小写字母、数字、标点符号和一些其他符号。

1. 非打印字符

非打印字符也可以是正则表达式的组成部分。

  • \cx:匹配由x指明的控制字符,例如\cM匹配一个Control-M或者回车符,x的值必须为A-Za-z之一
  • \f:匹配一个换页符
  • \n:匹配一个换行符
  • \r:匹配一个回车符
  • \s:匹配任何空白字符,包括空格、制表符和换页符等,等价于[\f\n\r\t\v]
  • \S:匹配任何非空白字符,等价于[^\f\n\r\t\v]
  • \t:匹配一个制表符
  • \v:匹配一个垂直制表符

2. 特殊字符

如果要匹配这些特殊字符的话,可以在其前面加上一个反斜杠进行转义。

  • \$:匹配输入字符串的结尾位置,如果设置了RegExpMultiline属性则$也匹配\n\r
  • ():标记一个子表达式的开始和结束位置,子表达式可以获取供以后使用
  • *:匹配前面的子表达式零次或多次
  • +:匹配前面的子表达式一次或多次
  • .:匹配除换行符\n外的任意单个字符
  • [:标记一个中括号表达式的开始
  • ?:匹配前面的子表达式零次或一次,或指明一个非贪婪限定符
  • \:将下一个字符标记为或特殊字符、或原义字、或向后引用、或八进制转义符
  • ^:匹配输入字符串的开始位置,如果实在方括号表达式中使用表示不接受该方括号表达式中的字符集合
  • {:标记限定符表达式的开始
  • |:指明两项之间的一个选择

3. 限定符

限定符用于指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。

  • *:匹配前面的子表达式零次或多次
  • +:匹配前面的子表达式一次或多次
  • ?:匹配前面的子表达式零次或一次
  • {n}:匹配确定的n
  • {n,}:至少匹配n
  • {n,m}:最少匹配n次最多匹配m

注意*+限定符都是贪婪的,因为它们会尽可能多的匹配文案,只要在它们的后面加上一个?就可以实现非贪婪或者最小匹配。

4. 定位符

  • ^:匹配输入字符串开始的位置
  • $:匹配输入字符串结尾的位置
  • \b:匹配一个单词边界,即字与空格间的位置
  • \B:非单词办结匹配

5. 选择

用圆括号将所有选择项括起来,相邻的选择项之间用|发那个,但用圆括号会有一个副作用使得相关的匹配都被缓存,此时可用?:放在第一个选项前来消除这种副作用。

6. 反向引用

对一个正则表达式模式或者部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从1开始,最多可以存储99个捕获的字表达式,每个缓冲区都可以用\n访问。

可以使用非捕获元字符?:?=?!来重写捕获。

反向引用有两个主要的用途:

  • 用于寻找文本中两个相同的相邻单词匹配项

相当于查询重复出现两次的单词,下面的python代码举了一个例子:

  1. import re
  2. """
  3. re.search(pattern, string, flags=0)
  4. pattern: 匹配的正则表达式
  5. string: 要匹配的字符串
  6. flags: 标志位, 用于控制正则表达式的匹配方式, 包括是否区分大小写和多行匹配等
  7. """
  8. # 查询重复出现两次的单词
  9. target_str = "Is is the cost of of gasoline going up up"
  10. match_str = re.findall(r'\b([a-z]+) \1\b', target_str, re.M|re.I)
  11. print("match str : ", match_str)
  12. ==================================================================
  13. # 输出结果
  14. # match str : ['of', 'up']
  • 还可用于将字符串分解成多个组件

比如我们可以将url解析成域名、端口等元素:

  1. import re
  2. """
  3. re.search(pattern, string, flags=0)
  4. pattern: 匹配的正则表达式
  5. string: 要匹配的字符串
  6. flags: 标志位, 用于控制正则表达式的匹配方式, 包括是否区分大小写和多行匹配等
  7. 返回值: 是一个list, 表示所有匹配到的子字符串
  8. """
  9. target_str = "http://www.runoob.com:80/html/html-tutorial.html"
  10. match_str = re.findall(r'(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)', target_str, re.M|re.I)
  11. print("match str : ", match_str[0])
  12. ==================================================================
  13. # 第一个括号子表达式包含 http
  14. # 第二个括号子表达式包含 www.runoob.com
  15. # 第三个括号子表达式包含 :80
  16. # 第四个括号子表达式包含 /html/html-tutorial.html
  17. # 输出结果
  18. # match str : ('http', 'www.runoob.com', ':80', '/html/html-tutorial.html')

7. 元字符

  • \:将下一个字符标记为特殊字符,或原义字符,或向后引用,或一个八进制转义符
  • ^:匹配输入字符串的开始位置
  • $:匹配输入字符串的结束为止
  • *:匹配前面的子表达式零次或多次
  • +:匹配前面的子表达式一次或多次
  • ?:匹配前面的子表达式零次或一次
  • {n}:匹配确定的n
  • {n,}:匹配至少n
  • {n,m}:匹配至少n次,至多m
  • ?:当该字符紧跟在任何一个其他限制符后面时表示匹配模式是非贪婪的
  • .:匹配除换行符\n \r外的任何单个字符
  • (pattern):匹配pattern并捕获这一结果
  • (?:pattern):匹配pattern并不捕获这一结果
  • (?=pattern):正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,这是一个非捕获匹配,即该匹配不需要获取供以后使用
  • (?!pattern):正向否定预查,在任何不匹配该pattern的字符串开始处匹配字符串,这是一个非获取匹配,即该匹配不需要获取供以后使用
  • (?<=pattern):反向肯定预查,与正向肯定预查类似,只是方向相反
  • (?<!pattern):反向否定预查,与正向否定预查类似,只是方向相反
  • x|y:匹配xy
  • [xyz]:匹配所包含的任意一个字符
  • [^xyz]:匹配未包含的任意字符
  • [a-z]:匹配指定范围内的任意字符
  • [^a-z]:匹配任何不在指定范围内的任意字符
  • \b:匹配一个单词边界,即单词和空格间的位置
  • \B:匹配非单词边界
  • \cx:匹配由x指明的控制字符
  • \d:匹配一个数字字符
  • \D:匹配一个非数字字符
  • \f:匹配一个换页符
  • \n:匹配一个换行符
  • \r:匹配一个回车符
  • \s:匹配任何空白字符,等价于[\f\n\r\t\v]
  • \S:匹配任何非空白字符
  • \t:匹配一个制表符
  • \v:匹配一个垂直制表符
  • \w:匹配字符、数字、下划线,等价于[A-Za-z0-9]
  • \W:匹配非字符、数字、下划线
  • \xn:匹配n,其中n为十六进制转义值
  • \n:标记一个八进制转义值或向后引用

运算符优先级

运算符优先级从高到低如下:

  • \:转义符
  • (),(?:),(?=),[]:圆括号和方括号
  • *, +, ?, {n}, {n,}, {n,m}:限定符
  • ^, $, \任何元字符、任何字符:定位点和序列(即位置和顺序)
  • |:“或”操作

Reference

[1] https://www.runoob.com/regexp/regexp-tutorial.html

[Skill]从零掌握正则表达式的更多相关文章

  1. [Skill]从零掌握80%的业务查询SQL语句

    前言 本篇文章的主要目的是帮助初学者快速入门SQL查询,从而解决实际业务中80%的SQL查询问题. 本文主要框架如下: 上篇:介绍SQL的语法顺序和执行顺序 中篇:介绍条件子句.分组查询和排序的细节 ...

  2. [Skill]VBA零基础入门及实践:根据链接展示图片

    简介 VBA(Visual Basic for Applications)是依附在应用程序(例如Excel)中的VB语言.只要你安装了Office Excel就自动默认安装了VBA,同样Word和Po ...

  3. 正则表达式 自学笔记整理记录 EASY REGEX~

    整理正则表达式篇                             -wuian7yulian 基础知识介绍 :  1> 字符串的组成: 对于字符串"ABC"来说,其包 ...

  4. [No0000100]正则表达式匹配解析过程分析(正则表达式匹配原理)&regexbuddy使用&正则优化

    常见正则表达式引擎引擎决定了正则表达式匹配方法及内部搜索过程,了解它至关重要的.目前主要流行引擎有:DFA,NFA两种引擎. 引擎 区别点 DFA Deterministic finite autom ...

  5. 正则表达式(Regular Expression, RegEx)学习入门

    1. 概述 正则表达式(Regular Expression, RegEx)是一种匹配模式,描述的是一串文本的特征. 正如自然语言中高大.坚固等词语抽象出来描述事物特征一样,正则表达式就是字符的高度抽 ...

  6. 正则表达式: NFA引擎匹配原理

    NFA引擎匹配原理 1       为什么要了解引擎匹配原理 一个个音符杂乱无章的组合在一起,弹奏出的或许就是噪音,同样的音符经过作曲家的手,就可以谱出非常动听的乐曲,一个演奏者同样可以照着乐谱奏出动 ...

  7. NFA引擎匹配原理

    1       为什么要了解引擎匹配原理 一个个音符杂乱无章的组合在一起,弹奏出的或许就是噪音,同样的音符经过作曲家的手,就可以谱出非常动听的乐曲,一个演奏者同样可以照着乐谱奏出动听的乐曲,但他/她或 ...

  8. Java 笔试面试 算法编程篇 一

    方法 1 /* ********************************************************************************** 1.编写一个程序, ...

  9. python 正则表达式之零宽断言

    零宽断言:用于查找特定内容之前或之后的内容,但并不包括特定内容本身.对于零宽断言来说,我认为最重要的一个概念是位置,零宽断言用于指定一个位置,这个位置应该满足一定的条件(它附近满足什么表达式),并且这 ...

随机推荐

  1. 法兰西金融专访SPC空投重磅来袭

    最近,法兰西金融日报联合德意志财经等知名金融媒体就SPC这一话题进行了专访. 法兰西金融日报记者德维尔斯问到,之前2020年的BGV项目等市场反响异常火爆,2021年已经来到,NGK目前有何新的大动作 ...

  2. uniapp 自定义弹窗组件

    先上效果: 组件源码:slot-modal.vue <template> <view class="modal-container" v-if="sho ...

  3. 【函数分享】每日PHP函数分享(2021-2-19)

    array_diff_uassoc - 用用户提供的回调函数做索引检查来计算数组的差集 说明 array_diff_uassoc ( array $array1 , array $array2 , a ...

  4. 哪些原因会导致JAVA进程退出?

    本文转载自哪些原因会导致JAVA进程退出? 导语 JAVA进程消失可能有哪些原因? 那我们就开一篇文章说一下这个问题,其实很easy的,无外乎三种情况. linux的OOM killer杀死 JVM自 ...

  5. ASP.NET Core WebApi版本控制

    前言: 在日常项目开发中,随着项目需求不断的累加.不断的迭代:项目服务接口需要向下兼容历史版本:前些时候就因为Api接口为做版本管理导致接口对低版本兼容处理不友好. 最近就像了解下如何实现WebApi ...

  6. Python序列之列表(一)

    在Python中,列表是一种常用的序列,接下来我来讲一下关于Python中列表的知识. 列表的创建 Python中有多种创建列表的方式 1.使用赋值运算符直接赋值创建列表 在创建列表时,我们直接使用赋 ...

  7. while、do...while和for循环

    一.循环 1.1 定义 当满足一定条件的时候,重复执行某一段代码的操作 while和for和do...while是java中的循环 二.while循环 2.1 定义 int i = 0: 初始化值 w ...

  8. 《C++ Primer》笔记 第12章 动态内存

    shared_ptr和unique_ptr都支持的操作 解释 shared_ptr sp或unique_ptr up 空智能指针,可以指向类型为T的对象 p 将p用作一个条件判断,若p指向一个对象,则 ...

  9. C++类的友元机制说明

    下面给出C++类的友元机制说明(对类private.protected成员访问),需要注意的是,友元机制尽量不用或者少用,虽然它会提供某种程度的效率,但会带来数据安全性的问题. 类的友元 友元是C++ ...

  10. TorchVision Faster R-CNN 微调,实战 Kaggle 小麦检测

    本文将利用 TorchVision Faster R-CNN 预训练模型,于 Kaggle: 全球小麦检测 上实践迁移学习中的一种常用技术:微调(fine tuning). 本文相关的 Kaggle ...