正则表达式使用文档

2023-10-27

通过网站 https://regex101.com/ 可以测试正则表达式的匹配结果及匹配过程.

本文章抛开各个编程语言实现差异, 仅做正则本身的介绍, 会尽量将正则这玩意说明白, 使得你看完这边文章后对正则基本可以运用自如.

温馨提示, 这篇文章会比较长, 大致浏览即可. 正确的方式是收藏起来, 等到使用正则的时候翻看

语法介绍

在平常进行字符串匹配的时候如何做呢? 比如希望从字符串Hello Word中匹配到第一个单词, 我们就会拿着Hello子串进行匹配.

正则表达式的表示与其相同, 区别是在子串匹配时每个字符都会进行原样匹配, 而正则表达式中会存在一些特殊符号, 这些符号会代表一些特殊的含义, 如a+的意思是匹配任意多个连续的a字符, 是不是十分简单?

如此说来, 要使用正则表达式, 关键点就在于了解其中的特殊字符上.

分类 字符 含义
单字符 . 任意字符(换行符除外)
\d 任意数字
\D 非数字
\w 字母数字下划线
\W 非字母数字下划线
$ 字符串结束位置
^ 字符串开始位置
空白符 \s 任意空白字符
\S 非空白字符(包括空格)
\r 回车
\n 换行
\f 换页
\t 制表符
\v 垂直制表符
量词 {m} 前面内容出现 m 次
{m,} >=m次
{m,n} m-n 次
* 同 {0,}
+ 同 {1,}
? 同 {0, 1}
范围选择 | 或. eg: `ab
[…] 单字符多选一. eg: [abcd] msg: a或b或c或d
[a-c] ASCII 表范围. eg: [a-z] msg: 所有小写字母
若其中的-是需要匹配的单字符, 需使用\-进行转义
[^…] 取反. []中标识的字符外的任意字符

以上所有均可以任意嵌套使用, 如:

  • https?|ftp: 可匹配 http https ftp

高级用法

分组

有这样一个正则表达式 ab{3} , 它会匹配字符串 abbb. 如果我们想要匹配字符串 ababab , 如何在正则表达式中指定令ab 重复3次呢?

用程序员的通俗思维想一下, 没错, 加括号. (ab){3} 的意思就是匹配字符串 ababab. 而这, 就是分组.

有的小朋友会问题了, 这不就是指定下优先级嘛, 和分组有什么关系? 为什么叫分组呢? 别急, 往下看

在正则表达式中, 分组有如下作用:

  1. 在表达式后面可以进行引用
  2. 在匹配结果中, 会将匹配的分组同时提取出来

正则引用分组

在正则表达式中, 可以通过 \1 来引用分组. 其中的数字是分组的编号, 从1开始. 从左往右依次递增.

比如正则表达式 (ab)(cd)\2\1 会匹配字符串 abcdcdab 同时会在结果中将2个分组提取出来.

image-20230910204040697

这里注意, 在有些编程语言的实现上, 通过$符号引用分组(比如 js), 用的时候再搜就行.

不引用分组

有的时候我们只是希望将多个字符合并, 并不需要引用分组. 这时可以通过 (?:...) 来指定不需要引用的分组.

嵌套分组

对于比较复杂的场景, 会存在括号嵌套括号的情况, 此时分组编号是全局的. 简单说, 左括号是第几个, 分组编号就是几.

比如正则表达式 (a(bc)d)\2\1 会匹配字符串 abcdbcabcd

分组应用场景

简单介绍几种可能预见的应用场景:

匹配重复单词

比如正则表达式: (\w+) \1

文本替换

比如这段python代码:

import re

test_str = 'hello, hujingnb is good, haha'
pattern = r'(\w+) is good'
repl = r'\1 is bad'
# hello, hujingnb is bad, haha
print(re.sub(pattern, repl, test_str))

比如常用的sublime工具中, 也可通过类似操作进行文本替换.

匹配模式

在匹配的时候, 可以通过设置(?i)来修改匹配模式为忽略大小写, 使用方式如下:

  • (?i)hello: 放在正则表达式最前面, 整个正则表达式均为忽略大小写模式
  • h(?i)hello: 放在正则表达式中间, 即从某处开始, 改为忽略大小写模式. 注意, 不是所有语言均可用
  • ((?i)hello) \1: 放在分组开头, 标识分某个分组改为忽略大小写模式. 注意, 不是所有语言均可用

可以调整的匹配模式如下, 匹配模式格式均为(?<model>), 使用方法相同, 多个模式可以放在一起使用, 如 (?is):

  • a: 测试 仅匹配 ASCII 字符, unicode 编码字符不进行匹配
  • i: 测试 忽略大小写
  • m: 测试 多行模式. 修改^$的行为, 改为匹配每一行的开头结尾
  • n: 测试 开启后, (...) 这种普通分组不会做为分组存在, 仅(?<name>...) 这种命名分组会进行捕获
  • s: 测试 .可以匹配任意符号, 包括换行符
  • u: 测试 匹配完整的 unicode 编码, 默认行为, 基本不需要设置
  • U: 测试 懒惰模式. 开启懒惰模式, 在此模式下, 量词后面加?为恢复贪婪模式
  • x: 测试 详细模式. 将正则表达式中的所有空格及换行均忽略, 且每行#后为注释内容. 匹配规则中的空格可使用\转义 (或者放到分组中使用, 也可以通过[ ]使用)

注意: 大部分语言都可以直接在正则表达式中修改匹配模式, 但部分语言不行, 比如:

  • js: /<正则>/<model>

边界匹配

在正则使用中, 可能会想要进行位置匹配, 但并不希望匹配内容出现在结果中. 于是就出现了这样一组符号, 仅用于匹配位置, 比如前面出现过的 ^$

用于匹配边界的符号有如下几种:

符号 demo 含义
^ 匹配 不匹配 匹配字符串的开始位置
$ 匹配 不匹配 匹配字符串的结束位置
\b 匹配 匹配单词边界, 边界包括 空格.- 等等符号, 注意_不是单词边界
\B 匹配 不匹配 匹配非单词边界, 与\b相反
\A 匹配 不匹配 ^差异 匹配字符串的开始位置, 与^相似. 但多行模式下, ^的行为会改为匹配行开始位置, \A行为不会改变
\Z 匹配 $差异 匹配字符串的结束位置, 与$相似. 同样, 在多行模式下, 行为不会改变
(?=...) 匹配 不匹配 前向肯定断言. 简单说, 右边匹配 ...
(?!...) 匹配 不匹配 前向否定断言. 简单说, 右边不匹配 ...
(?<=...) 匹配 不匹配 后向肯定断言. 简单说, 左边匹配 ...
(?<!...) 匹配 不匹配 后向否定断言. 简单说, 左边不匹配 ...

扩展语法

所有扩展语法格式均为为(?...). (反过来不成立)

注意, 扩展语法并不是所有编程语言都支持的, 在使用前可前往网站测试是否支持.

命名分组

使用编号引用分组的方式并不友好, 甚至有时候改了下正则表达式, 后面编号都要改一遍. 因此, 我们可以给分组起个名.

  • (?P<xxx>...): 给分组起名为 xxx
  • (?P=xxx): 引用 xxx分组

比如正则表达式 (?P<reg_name>ab)(?P=reg_name) 会匹配字符串 abab

注意 命名分组也会占用分组的编号哦, 也就是说 (?P<reg_name>ab)(?P=reg_name)(?P<reg_name>ab)\1 效果是一样的.

测试

分支判断

根据前面是否匹配到分组信息, 来使得后面能够有不同的匹配行为.

语法为: (?(<group_id>/<group_name>)<yes-pattern>|<no-pattern>) , 前面指定分组编号或者名字, 如果分组存在, 则使用 <yes-patterm> 进行匹配, 否则使用 <no-pattern> 进行匹配.

比如这个例子, ^(<)?(\w+)(?(1)>|$)$, 可以匹配到字符串 <aaa>aaa, 也就是< 开头的必须由 > 结尾.

注释

语法 (?#这部分是注释)

匹配规则

下面介绍下几种匹配规则:

  • 贪婪模式: 尽可能多的匹配. 是正则匹配时的默认模式
  • 懒惰模式: 尽可能少的匹配. 通过在量词后添加?指定. 如a*? 就是a*的懒惰版本
  • 独占模式: 在匹配过程中不进行回溯. 通过在量词后添加+指定. 如a++就是a+的独占版本

简单对着几种规则进行说明

贪婪模式

贪婪模式其实就是我们平常最进场使用的模式. 其原则是向后查找尽量长的字符串进行匹配.

比如使用正则b*来匹配字符串abbbc, 能够匹配到如下内容:

位置(前闭后开) 匹配内容
0-0
1-4 bbb
4-4
5-5

匹配过程大致如下:

  1. 0-0: 匹配第一个字符, 发现不是 a, 输出空
  2. 1-4: 一直匹配到字母c发现匹配不上了, 输出bbb
  3. 剩下的同理

懒惰模式

匹配过程与贪婪模式相似, 区别是只要有能够匹配到的, 就输出, 会输出符合规则的最短子串.

还用上面相同的例子举例, 使用正则b*?匹配字符串abbbc, 能够匹配到如下内容:

位置(前闭后开) 匹配内容
0-0
1-1
1-2 b
2-2
2-3 b
3-3
3-4 b
4-4
5-5

与上面的一对比, 区别是不是就很明显了? 这次匹配到的是没单个b字符, 就连每个b字符左面的空字符都匹配上了.

匹配过程就不再赘述了. 这里用一个更加明显且常用的场景来说明贪婪模式懒惰模式的区别, 当我们匹配字符串"hi mom" and "hi son"时:

  • ".*" : 贪婪模式下, 匹配到的是字符串"hi mom" and "hi son"
  • ".*?": 懒惰模式下, 则会分别匹配到字符串"hi mom""hi son"

独占模式

要说明独占模式, 得先简单说一下正则匹配的回溯现象.

比如, 使用正则 ab+bc 匹配字符串 abbbc的时候, 在贪婪模式下(下方的括号为了标明当前匹配的位置):

正则匹配位置 字符串匹配位置 说明
(a)b+bc (a)bbbc 字符 a 完成匹配, 继续下一个匹配
a(b+)bc a(b)bbc 此时, 要匹配字符 b 的数量为 >= 1, 因此会继续向后匹配
正则位置不变, 字符串匹配后移(后续相同操作忽略)
a(b+)bc abbb© 当匹配到这个位置的时候, 发现已经匹配不上了. 则字符串会向前移动, 以继续完成匹配.
ab+(b)c abb(b)c 此时, 字符串将已经匹配过的字符又吐出来了. 这个过程就被称为回溯
后续完成匹配, 不再赘述

如果正则是ab+bbc的话, 匹配相同的字符串甚至会发生多次回溯. (懒惰模式也存在回溯现象, 不再赘述)

而回溯现象是及其影响性能的. 而独占模式则是将回溯直接关掉, 匹配性能更好, 但是对正则书写的要求也更高些.

比如匹配abbbc字符串时, 开启独占模式的匹配规则ab++bc会匹配不到任何数据.

ab++c则是能够匹配到字符串abbbc的, 因为匹配过程无需回溯,

这里说句题外话, 在有些编程语言中不支持回溯模式, 比如Go, Python中使用也需要通过regex库.

回溯现象真实场景

你以为回溯现象造成的性能微乎其微么? 不, 有这样一篇文章一个由正则表达式引发的血案, 讲述了因为正则回溯而导致的 CPU 爆满, 感兴趣的去原文看一下.

简单来说, 就是正则表达式 ^([a-z]|[a-z])+$ 在进行匹配的时候,因为a-z在前后组合中重复出现了, 导致大量回溯后的重复判断 . 如果所有的字符都能够成功匹配到前一个组合, 问题还不大, 但一旦有一个字符不匹配就会发生回溯, 且不匹配的字符越靠后, 回溯的层级越深. 查看回溯匹配

对于这种情况如何修改呢?

  1. 将重复匹配去掉, 改为 ^[a-z]+$
  2. 使用独占模式防止回溯. ^([a-z]|[a-z])++$

回溯的介绍, 也可参考此文章

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正则表达式使用文档 的相关文章

  • 去除多余的0;正则表达式:去掉数字(整数、小数)前面多余的零

    方案1 来源 http zhidao baidu com question 277893180 html 如果是整数 去掉整数前的零 例如 0098765 gt 98765 如果是小数 去掉小数前的零 例如 000 333 gt 0 333
  • Shell中正则表达式

    1 正则表达式介绍 1 正则表达式 通常用于判断语句中 用来检查某一字符串是否满足某一格式 2 正则表达式是由普通字符与元字符组成 3 普通字符包括大小写字母 数字 标点符号及一些其他符号 4 元字符是指在正则表达式中具有特殊意义的专用字符
  • 制作自己的 Kindle 电子书

    想象以下场景 你刚收到一台新的 Kindle Paperwhite 心中已然响起了轰轰烈烈的 我今年 或这个冬天 一定要阅读 100 本书 结果发现 想看的书 Amazon 上找不到 或者排版很糟糕 如何解决 自己动手做呗 准备工作 我使用
  • Jmeter参数化--后置处理器之正则表达式提取器

    在接口测试中 很多都需要依赖前一个请求的响应数据放到后一个请求的请求数据中来 在Jmeter中提供了正则表达式提取器来提取响应数据中的片段 本次使用的实例是微信公众号的客服发消息 在这个接口中 需要用到access token接口返回的to
  • VB.Net常用的正则表达式(实例)

    d 非负整数 正整数 0 0 9 1 9 0 9 正整数 d 0 非正整数 负整数 0 0 9 1 9 0 9 负整数 d 整数 d d 非负浮点数 正浮点数 0 0 9 0 9 1 9 0 9 0 9 1 9 0 9 0 9 0 9 1
  • 截取oracle字符串中的数字(转载)

    截取oracle字符串中的数字 云淡风轻博客 博客园 cnblogs com 方法一 如果Oracle版本不是太低的话 使用 正则表达式函数 REGEXP SUBSTR 处理 REGEXP SUBSTR有5个参数 分别是 第一个是输入的字符
  • 常用js

    1 去掉字符串两端的空格 对字符串去两端空格 function stringTrim str if str null str undefined return null 用正则表达式将前后空格 用空字符串替代 return str repl
  • 【PAT乙级】旧键盘打字

    题目描述 旧键盘上坏了几个键 于是在敲一段文字的时候 对应的字符就不会出现 现在给出应该输入的一段文字 以及坏掉的那些键 打出的结果文字会是怎样 输入格式 输入在 2 行中分别给出坏掉的那些键 以及应该输入的文字 其中对应英文字母的坏键以大
  • Java使用 java.util.regex.Pattern 正则表达式校验参数值是否规范

    场景 java中我们可以利用 Pattern 注解对某个入参进行规则校验 但有些特殊参数在接口入口处不方便校验 需要在代码中校验 一 使用 Pattern 注解校验 Pattern regexp a zA Z0 9 message xxx号
  • SparkSQL HiveSQL 常用正则表达式

    SparkSQL HiveSQL 常用正则表达式 目录 SparkSQL HiveSQL 常用正则表达式 1 匹配汉字 2 匹配手机号码 3 匹配身份证 4 SparkSQL HiveSQL 常用正则函数 5 SparkSQL 分组 聚合
  • 4.4.5 密码验证(2)

    4 当且仅当含数字和字母的密码验证 如果密码当且仅当包含数字和字母 那么该密码的强度是中等强度 当然 它的安全性一般 以下正则表达式能够验证当且仅当包含数字和字母的密码 da zA Z d a zA Z da zA Z 74 正则表达式 7
  • 用Requests和正则表达式爬取猫眼电影(TOP100+最受期待榜)

    目标站点分析 目标站点 猫眼榜单TOP100 如下图 猫眼电影的翻页offset明显在URL中 所以只要搞定第一页的内容加上一个循环加上offset就可以爬取前100 流程框架 1 抓取单页内容 利用requests请求目标站点 得到单个网
  • 知道这20个正则表达式,能让你少写1,000行代码

    正则表达式 一个十分古老而又强大的文本处理工具 仅仅用一段非常简短的表达式语句 便能够快速实现一个非常复杂的业务逻辑 熟练地掌握正则表达式的话 能够使你的开发效率得到极大的提升 正则表达式经常被用于字段或任意字符串的校验 如下面这段校验基本
  • Java正则校验密码至少包含:字母数字特殊符号中的2种

    一 语法 字符 说明 将下一字符标记为特殊字符 文本 反向引用或八进制转义符 例如 n匹配字符 n n 匹配换行符 序列 匹配 匹配 匹配输入字符串开始的位置 如果设置了 RegExp 对象的 Multiline 属性 还会与 n 或 r
  • 表示数值的字符串(含思路解答示意图)【剑指offer——JAVA实现】

    题目描述 请实现一个函数用来判断字符串是否表示数值 包括整数和小数 例如 字符串 100 5e2 123 3 1416 和 1E 16 都表示数值 但是 12e 1a3 14 1 2 3 5 和 12e 4 3 都不是 解法一 思路 状态机
  • 正则表达式(日期、金额、特殊字符)_java语言

    正则表达式 java 正则表达式在线测试网站 个人觉得还算精确 http tool chinaz com regex 备注 如有错误 希望留言指出 虚心请教 金额格式 正数 包含至多2位小数 第1种形式 校验金额格式是否正确 正数 包含至多
  • Java 正则表达式工具类大全

    import java util regex Matcher import java util regex Pattern author nql Description 验证工具类 date now public class Validat
  • 天梯赛字符串替换题 “ 6翻了” Python 正则表达式替换

    输入格式 输入在一行中给出一句话 即一个非空字符串 由不超过 1000 个英文字母 数字和空格组成 以回车结束 输出格式 从左到右扫描输入的句子 如果句子中有超过 3 个连续的 6 则将这串连续的 6 替换成 9 但如果有超过 9 个连续的
  • 【golang】error parsing regexp: invalid or unsupported Perl syntax (正则表达式校验密码)

    要在 Go 中编写密码校验规则 确保密码不少于8位且包含数字和字母 你可以使用正则表达式和 Go 的 regexp 包来实现 以下是一个示例代码 错误示范 package main import fmt regexp func valida
  • 常用表单正则表达式

    校验 大小写字母 汉字 export const verifyCheEng a zA Z p sc Han gu 校验 数字 大小写字母 汉字 export const verifyCheEngNum a zA Z0 9 p sc Han

随机推荐

  • linux目录和用户组

    一 目录结构 1 根目录 绝对路径 2 bin 二进制 普通用户常用系统命令 3 sbin 管理员用的系统命令 4 dev 设备信息 5 home 普通用户家目录 6 root root 家目录 7 lib 32位库文件 8 lib64 6
  • [OGRE]基础教程来四发:来谈一谈地形系统

    OGRE 基础教程来四发 来谈一谈地形系统 标签 OGRE 2013 10 09 17 22 2238人阅读 评论 1 收藏 举报 分类 OGRE 11 版权声明 本文为博主原创文章 未经博主允许不得转载 英文链接如下 http www o
  • 传统算法与神经网络算法,进化算法优化神经网络

    神经网络算法与进化算是什么关系 应该没有太大的关系吧 我对遗传算法了解一点 遗传算法主要用来优化神经网络第一次运行时所用的连接权值 因为随机的连接权值往往不能对针对的问题有比较好的收敛效果 Matlab神经网络工具箱自动生成的初始权值其实已
  • Redis第九讲 Redis之Hash数据结构Dict字典哈希算法与hash存储过程

    Redis dict使用的哈希算法 前面提到 一个kv键值对 添加到哈希表时 需要用一个映射函数将key散列到一个具体的数组下标 Redis 目前使用两种不同的哈希算法 MurmurHash2 是种32 bit 算法 这种算法的分布率和速度
  • java imap 乱码_用 imaplib 只取信件头会取到乱码,取整封信则正常

    最近用 Python 的 imaplib 和 email 从一个 gmail 信箱中取信 因为信可能有很多 而我只想取特定发件人发来的信 所以就只先取信头 通过类似 rv data self M fetch num BODY HEADER
  • 口语理解任务源码详解系列(四)Ernie模型实现

    Ernie模型实现口语理解任务 一 构建词表 def word2id func raw dataset returns a dictionary of words and their ids print raw dataset raw da
  • The connection property 'zeroDateTimeBehavior' only accepts values of the form

    前景概述 表user info中created time 设计为 created time timestamp not null default current timestamp java插入数据时没有填写createdTime字段 就抛
  • 自定义view之水波浪进度球

    这段时间项目做完了 本以为可以偷懒一段时间 结果领导又接了一个车载项目让我做 很气但是没办法 还是得搞 谁让我是搬砖的呢 今天搞了一个水波纹的自定义控件 先看效果 第一眼还是觉得可以看的 其实我觉得有点丑 ui妹子说挺好看 好吧 那就这样吧
  • 【设计经验】5、Verilog对数据进行四舍五入(round)与饱和(saturation)截位

    原文链接 https www cnblogs com liujinggang p 10549095 html
  • 浅谈chrony服务

    浅谈chrony服务 chrony概念 Chrony 是 NTP 客户端的替代品 Chrony 的优势 更快的同步只需要数分钟而非数小时时间 从而最大程度减少了时间和频率 误差 对于并非全天 24 小时运行的虚拟计算机而言非常有用 能够更好
  • 图的m着色问题——回溯法及其优化(变量排序MRV, 值排序MCV, 前向检查ForwardChecking, 智能回溯, 边相容,K阶相容)python C++实现

    文章目录 图的m着色问题背景 背景知识 问题描述 回溯法的原理及其实现 回溯法基本思想 朴素回溯法解决图的m着色问题 回溯优化策略 回溯法优化 变量排序MRV 回溯法优化 值排序MCV 回溯法优化 前向检查ForwardChecking 边
  • [Transformer]TNASP: A Transformer-based NAS Predictor with a Self-evolution Framework

    TNASP 基于Transformer和自进化的的NAS Predictor Abstract Section I Introduction Section II Related Work Training based network pe
  • C++11-14 第5讲 Uniform Initialization 一致初始化值 &initializer_list

    版权说明 本博文属于个人笔记 本人保留对本文的所有权益 未经许可不得以任何形式转载 Uniform Initialization 一致初始化值 新手困惑初始化怎么写 可能发生在 中 任何初始化都用共通写法 旧 Rect r1 1 2 3 R
  • 6.3.3法线贴图

    1 法线贴图必须与灯光同时进行 2 从法线纹理取得模型空间的法线 再根据切线空间到世界空间的变换矩阵 传递到世界坐标系的法线 再进行计算
  • 和你一起draw9patch

    前言 在工作当中 你总会遇到制作点9图片的时候 我就在公司的新项目中遇到了 很多人说 这交给UI妹妹做就好了 为啥要烦劳我们自己动手 第一呢 作为程序员的我们 多学点东西是没错的 第二呢 UI妹妹做的点9图片产生的效果不是你想要的 一 制作
  • 小程序如何使用vant

    小程序如何使用vant 使用 Vant Weapp 前我强烈的建议大家去看下微信官方的 小程序简易教程 和 自定义组件介绍 点击下方超链接 https youzan github io vant weapp quickstart 第一步 首
  • 目标检测入门概念知识

    一个常见的目标检测网络 其本身往往可以分为一下三大块 Backbone network 即主干网络 目标检测网络的主体结构 是目标检测网络最为核心的部分 大多数时候 backbone选择的好坏 对检测性能影响是十分巨大的 代表网络有 VGG
  • ORB_SLAM2特征匹配

    ORB SLAM2特征匹配 SearchByProjection 使用于运动模型跟踪 函数原型 函数简介 知识难点 由两帧绝对位姿推出两帧相对位姿 前进与后退对搜索范围的影响 描述子的比较 方向一致性检测 运用于局部地图跟踪 函数原型 函数
  • 注解处理器APT在java中的实现

    概念理解 APT 英文全名 Annotation Processor Tool 即 注解处理器 它是 javac 的一个工具 这是Sun为了帮助注解的处理过程而提供的工具 apt被设计为操作Java源文件 而不是编译后的类 作用阶段示意图如
  • 正则表达式使用文档

    通过网站 https regex101 com 可以测试正则表达式的匹配结果及匹配过程 本文章抛开各个编程语言实现差异 仅做正则本身的介绍 会尽量将正则这玩意说明白 使得你看完这边文章后对正则基本可以运用自如 温馨提示 这篇文章会比较长 大