正则表达式-分组与后向引用

2023-11-05

前文中,已经总结了正则表达式中的常用字符、次数匹配、位置匹配等,这篇文章中,我们来了解一下正则中的”分组”与”后向引用”。

什么是分组?什么是后向引用?我们慢慢聊。

先来说说什么是分组。

算了,思考了半天,我也不知道从何说起,先看个示例吧,根据示例去描述反而更加清晰,示例如下。
在这里插入图片描述
上述示例中,我们使用到了之前所了解到的”连续次数匹配”,”{2}”表示其前面的字符连续出现的2次,即可被匹配到。

但是,正如上图所示,”{2}”所影响的字符只是其前面的单个字符,也就是上例中的字母o

所以,上例中,helloo被匹配到了,hellooo也被匹配到了,因为”hell”字符串后面的确出现了2次字母o

但是,如果我们想要从上例中的文本中找出,2次连续出现的hello字符串,该怎么办呢?

正如你所看到的,”hello{2}”并不能表示”hellohello”,它只能表示”helloo”,那么,我们该怎么办呢?

这个时候,我们就需要用到”分组”,将”hello”当做一个”分组”,当做一个”整体”,才可以达到我们的目的,示例如下
在这里插入图片描述
正如上图所示,”(hello)”表示将hello字符串当做一个整体,所以,”{2}”所影响的字符就是前面的”hello字符串”(这个整体)。

所以,”(hello){2}”这个正则表达式就表示hello字符串连续出现两次,也就是”hellohello”

没错,”( )”就表示分组。

“( )”表示将其中的内容看做一个分组,看做一个整体。

分组还可以嵌套,什么意思呢?我们来看一个例子。
在这里插入图片描述
上图中的正则表达式猛一看有些复杂,但是我们一点一点的拆开来看,就比较容易理解了,没错,我们先按照上图所示,将”红线部分”与”蓝线部分”拆成两部分

蓝线部分为”{2}”,表示之前的字符连续出现两次

红线部分为”(ab(ef){2})”,可以看到,红线部分的两侧正好由”( )”组成,由此可见,红线部分应该作为一个整体,应该作为一个分组被操作,再结合之前的蓝线部分,即可得知,红线部分应该作为一个整体连续出现两次。

那么,我们把红线部分最外侧的”( )”去掉,红线部分内侧的正则为”ab(ef){2}”,可以看到,红线部分内侧的正则中还有一组分组符号,就是”(ef)”,这个分组符号把ef当做了一个整体,所以,”ab(ef){2}”表示字符串ab后面跟随了2个连续出现的ef,那么,”ab(ef){2}”就表示字符串”abefef”。

逆推回去,我们把红线内侧的正则替换为”abefef”,于是,上例中的正则就表示”(abefef){2}”,最终如上图所示,2次连续出现的abefef被匹配到了。

上例中,红线部分一共包含两个分组符号,最外侧的”( )”中又包含了另一个”( )”,这就是分组符号的嵌套。

我想,我应该说清楚了。

那么,我们再来聊聊什么是后向引用。

之所以先介绍分组,是因为后向引用是以分组为前提的,如果想要实现后向引用,则必须先进行分组。

那么”后向引用”是什么意思呢?

如果直接放出概念,我不容易描述,你也不容易理解,我们还是先来看个小例子吧,示例文件如下。
在这里插入图片描述
如果我们想要使用正则去匹配上述示例中的两行文本,我们改怎么办呢?

我们可以使用如下正则表达式去匹配。
在这里插入图片描述
“H.{4}”表示大写字母H的后面跟随了4个任意字符,其中”.”表示任意单个字符,我们在前文中已经举例演示过,此处不再赘述。

所以,”H.{4}”既可以匹配到Hello,也可以匹配到Hiiii,那么,上述两行文本都被匹配到了。

此时,我们修改一下示例文件,在示例文件中再添加一行测试文本,修改后的测试文件内容如下

在这里插入图片描述
如上图所示,我们添加了一行文本,这行文本以Hello开头,以Hiiii结尾。

我们使用刚才的正则,能够匹配到这一行新添加的文本吗,我们来试试。

在这里插入图片描述
可以看到,新添加的一行文本也被匹配到了,因为”H.{4}”表示大写字母H的后面跟随了4个任意字符,最后一行也满足条件,所以也被匹配到了。

但是此刻,我有了新需求~~

我只想从上例中找出”world”前后单词相同的那些行,换句话说就是,world之前的单词是Hello,world之后的单词也要是Hello,world之前的单词是Hiiii,world之后的单词也要是Hiiii,只有这种行满足条件。

上例中第三行则不满足条件,因为上例的第三行中,world之前的单词是Hello,而world之后的单词是Hiiii,前后不一致,所以不满足我的条件。

那么我该怎么办呢?之前的正则肯定不行,因为之前的正则也能够将上例中的第三行匹配到。

这个时候,就需要用到”后向引用”,示例如下。

在这里插入图片描述
可以看到,使用上述正则,即可达到我们的目的,只有world前后的单词完全相同时,才会被匹配到。

那么,上例中的正则是什么意思呢?我们仍然拆成两部分来介绍,以便我们理解。

上例的红线部分为:”(H.{4})”

上例的蓝线部分为:”\1″

红线部分的正则与之前示例中的正则只有一点点区别,就是在原来的基础之上添加了分组,将”H.{4}”变成了”(H.{4})”,但是它的大概含义并没有改变,”(H.{4})”表示大写字母H的后面跟随了4个任意字符,并且字母H与后面的4个字符将作为一个整体。那么,为什么要在原来的基础上添加分组呢?这是因为,如果想要实现后向应用,则必须以分组为前提,现在我们暂且不纠结这一点,之后回过头来看,就会明白。

蓝色部分的正则为”\1″,它有什么含义呢?

“\1″表示整个正则中第1个分组中的正则所匹配到的结果,这样说可能不容易理解,我们用大白话说一遍。

在上例中,整个正则中只出现了1个分组,就是”(H.{4})”,当它与示例文件中的第一行文本进行匹配时,会匹配到Hello字符串,这时,”\1″就表示Hello字符串。

当正则”(H.{4})”与示例文件中的第二行文本进行匹配时,会匹配到Hiiii字符串,这时,”\1″就表示Hiiii字符串。

也就是说,”\1″必须与整个正则中第1个分组中的正则(也就是红色部分的正则)所匹配到的结果相同。

换句话说就是,”\1″引用了整个正则中第1个分组中的正则(也就是红色部分的正则)所匹配到的结果。

如果你还没有懂,看图理解吧。
在这里插入图片描述
现在回头想想,你知道为什么必须为”H.{4}”添加分组了吗?因为,当我们为”H.{4}”添加了分组以后,”H.{4}”就变成了整个正则中第1个分组中的正则,当”H.{4}”匹配到的结果为Hello时,”\1″就引用了Hello,当”H.{4}”匹配到的结果为Hiiii时,”\1″就引用了Hiiii。

这就是所谓的”后向引用”。

上述描述看一遍可能不容易立马理解,可以重复仔细的多看几遍,慢慢就会理解了。

聪明如你,一定想到了。

“\1″表示引用整个正则中第1个分组中的正则所匹配到的结果,那么,”\2″呢?没错,正如你所想。

“\2″表示引用整个正则中第2个分组中的正则所匹配到的结果

示例如下
在这里插入图片描述
如上图所示,”\2″引用了上图中”绿线部分的正则”所匹配到的结果,而上图中”绿线部分的正则”就是”整个正则表达式中第2个分组中的正则”。

那么,以此类推,”\3″、”\4″、”\5″、”\6″所表达的意思就不言而喻了。

再次强调,使用后向引用的前提是将需要引用的部分分组。

不过,当分组嵌套时,我们应该怎样区分哪个分组是第1个分组,哪个分组是第2个分组呢?

我们通过一个小示例,即可明白,为了尽量简化整个正则,我们直接将一些字符分组即可,示例如下。
在这里插入图片描述
上述正则表达式中,一共出现了两个分组,一个分组嵌套着另一个分组。
在这里插入图片描述
可以从上图中看出,红色标注的符号是一对分组符号,蓝色标注的符号是一对分组符号,红色分组嵌套这蓝色分组。

虽然上例中没有使用到”后向引用”,但是,当我们需要使用”后向引用”时,这两个分组哪个才是第1个分组,哪个是第2个分组呢?

当我们需要使用后向引用时,红色分组为第1个分组,蓝色分组为第2个分组。

换句话说就是,当使用后向引用时,”\1″引用的是红色分组所匹配的结果,”\2″引用的是蓝色分组所匹配的结果。

为什么呢?原因就是,分组的顺序取决于分组符号的左侧部分的顺序,如下图所示

在这里插入图片描述
由于红色分组的左侧部分排在最前面,所以红色分组是整个正则中的第1个分组。

由于蓝色分组的左侧部分排在第2位,所以蓝色分组是整个正则中的第2个分组。

注意:排序时也仅仅按照分组符号的左侧部分排序,分组符号的右侧部分不算在排序范围内。

好了,”分组”与”后向引用”就总结到这里,我想我应该说明白了,描述起来好费力~~~希望能够帮到你。

之前说过,在Linux中,正则表达式分为基础正则表达式与扩展正则表达式。

而我们之前所描述的符号都属于基本正则表达式。

在以后的文章中,我们会接触到扩展正则表达式,但是不用害怕,它们的用法都是相似的,而且写法也差不多,学会基本正则表达式以后,再学习扩展正则表达式,几乎不会费力。

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

正则表达式-分组与后向引用 的相关文章

  • 正则表达式中的“^“这个符号的一些思考

    在学习正则表达式的时候 一些常见的规则我们都不难理解 但是有 一个正则表达式中的特殊字符让我一直有点搞不懂 就是 这个字符 文档上给出了解释是匹配输入的开始 如果多行标示被设置成了true 同时会匹配后面紧跟的字符 比如 A 会匹配 An
  • java用正则表达式脱敏手机号

    一种正则形式 在Java开发中有时候需要对敏感字段数据脱敏 废话不多说 直接上代码 脱敏手机号 param str return 脱敏后字符串 public static String maskPhone String str return
  • Python---正则表达式

    专栏 python 个人主页 HaiFan 专栏简介 Python在学 希望能够得到各位的支持 正则表达式 前言 概念 作用和特点 使用场景 正则符号 re模块 re compile match search span findall gr
  • js验证邮箱的正则表达式

    最近小小研究了一下正则表达式 觉得写正则表达式还挺有意思的 先想推荐一个网址 把正则表达式的基本语法都总结了 很不错 https msdn microsoft com zh cn library ae5bf541 v vs 100 aspx
  • python正则表达式从字符串中提取数字的思路详解(转载)

    python从字符串中提取数字 使用正则表达式 用法如下 总结 匹配字符串的开始 匹配字符串的结尾 b 匹配一个单词的边界 d 匹配任意数字 D 匹配任意非数字字符 x 匹配一个可选的 x 字符 换言之 它匹配 1 次或者 0 次 x 字符
  • Shell脚本攻略:通配符、正则表达式

    目录 一 理论 1 通配符 2 正则表达式 二 实验 1 通配符 2 正则表达式 一 理论 1 通配符 1 概念 通配符只用于匹配文件名 目录名等 不能用于匹配文件内容 而且是已存在的文件或者目录 各个版本的shell都有通配符 这些通配符
  • Java正则工具类:字母数字下划线、数据库url校验等

    文章目录 前言 一 正则基础语法 二 正则工具类 总结 前言 本文内容观摩的是其他作者的代码 在基础上增加修改了一些 参考原文地址 java用正则表达式 提示 以下是本篇文章正文内容 下面案例可供参考 一 正则基础语法 字符 描述 匹配输入
  • SparkSQL HiveSQL 常用正则表达式

    SparkSQL HiveSQL 常用正则表达式 目录 SparkSQL HiveSQL 常用正则表达式 1 匹配汉字 2 匹配手机号码 3 匹配身份证 4 SparkSQL HiveSQL 常用正则函数 5 SparkSQL 分组 聚合
  • JavaScript最后分水岭——正则表达式

    个人简介 个人主页 微风洋洋 博客领域 编程基础 后端 写作风格 干货 干货 还是tmd的干货 精选专栏 JavaScript 支持洋锅 点赞 收藏 留言 好久不见 甚是想念 大家好 我是微风洋洋 也可以叫我洋锅 细心地小伙伴可能已经发现
  • 爬虫入门_3:数据解析及案例实战

    聚焦爬取 爬取页面中指定的页面内容 编码流程 指定url 发起请求 获取响应数据 数据解析 持久化存储 数据解析分类 正则 re M 多行匹配 re S 单行匹配 bs4 xpath 数据解析原理概述 解析的局部的文本内容都会在标签之间或者
  • grep命令

    grep 全称是global regular expressions print 功能就是查找匹配模式的行 grep对文本内容的处理是以行为单位 输出也是输出匹配的行 也可以使用两个变种程序egrep和fgrep egrep与grep E相
  • 对字符串进行正则取子串

    题目是这样的 对一段HTML网页内容 解析出其中所有的键值对 比如其中type text type为属性 text为值 二者为一个键值对 内容如下
  • test is not a function (js正则表达式匹配问题)

    js中正则表达式匹配时 如果使用test函数 就必须不带引号 并且必须是 定义的规则变量 test 要测试的string 定义变量规则不要带引号 会错误的 如果不使用test 使用match则可以带引号 var re 1 9 d 4 10
  • 【Linux命令—shell】正则表达式

    正则表达式 regular expression 描述一个字符集合的表达方式 模糊匹配 目录 1 基本正则 2 扩展正则 3 兼容的正则 perl 4 综合案例练习 1 基本正则 演示如下 2 扩展正则 注意 grep不支持扩展正则 如果需
  • 元字符的详细解析

    上一篇文章介绍了正则的用处以及正则中这些元字符的基本含义 但是如果我们只知道那些元字符的含义 不知道怎么使用和加以练习 那么对于正则我们还只是看见了门槛 并没有踏入 那么本篇文章就让我们迈起脚步正式走入正则的世界吧 let s go 我的学
  • C#中Validating和Validated事件

    您可能经常需要检查用户输入到 Windows 窗体中的信息是否有效 例如 如果您有一个电话号码的 TextBox 控件 则可以检查该控件是否只包含适当的字符 数字 括号和连字符等等 通常 可使用正则表达式验证用户输入的数据 了解Valida
  • QRegexp、QRegularExpression的用法学习

    QRegexp QRegularExpression的用法学习 文章目录 QRegexp QRegularExpression的用法学习 QRegexp QRegularExpression 模式选项 QRegexp Regexp 由表达式
  • 表示数值的字符串(含思路解答示意图)【剑指offer——JAVA实现】

    题目描述 请实现一个函数用来判断字符串是否表示数值 包括整数和小数 例如 字符串 100 5e2 123 3 1416 和 1E 16 都表示数值 但是 12e 1a3 14 1 2 3 5 和 12e 4 3 都不是 解法一 思路 状态机
  • [网络安全自学篇] 十四.Python攻防之基础常识、正则表达式、Web编程和套接字通信(一)

    这是作者的系列网络安全自学教程 主要是关于网安工具和实践操作的在线笔记 特分享出来与博友共勉 希望您们喜欢 一起进步 前文分享了Wireshark抓包原理知识 并结合NetworkMiner工具抓取了图像资源和用户名密码 本文将讲解Pyth
  • SourceInsight

    1 开胃菜 初级应用 1 1 选择美丽的界面享受工作 虽然不能以貌取人 但似乎从来没有人责备以貌取软件的 SI的华丽界面 绝对符合现代花花世界的人的审美趣味 在SI中 我们可以轻松地把各种类型关键字 变量 标志符 函数 宏 注释等定义为不同

随机推荐

  • 变量、作用域与内存

    目录 原始值与引用值 动态属性 复制值 传递参数 确定类型 执行上下文与作用域 作用域链增强 变量声明 1 使用var 的函数作用域声明 2 使用let 的块级作用域声明 3 使用const 的常量声明 标识符查找 垃圾回收 标记清理 最常
  • MPI测试程序

    include
  • mysql cmd命令行 创建数据库 表 基础语句

    一 连接MYSQL 格式 mysql h主机地址 u用户名 p用户密码 1 连接到本机上的MYSQL 首先打开DOS窗口 然后进入目录mysql bin 再键入命令mysql u root p 回车后提示你输密码 注意用户名前可以有空格也可
  • A*寻路算法 lua

    function InitMap self AMap for i 1 10 do self AMap i for j 1 10 do local map map x i map y j map g 999 map h 0 map f 0 m
  • 如何运行一个CFDEM tutorial case

    新手入门 万里长征第一步 安装完CFDEM后 我们知道有很多tutorial可以教我们怎么设置合理的参数 很多tutorial case里都有写好的Allrun脚本 最简单的方法就是运行Allrun脚本走一遍流程 准备工作 复制随便一个tu
  • 当里个当,免费的HTML5连载来了《HTML5网页开发实例详解》连载(一)

    读懂 HTML5网页开发实例详解 这本书 你还在用Flash嘛 帮主早不用了 乔布斯生前在公开信 Flash之我见 中预言 像HTML 5这样在移动时代中创立的新标准 将会在移动设备上获得胜利 国际巨头Google 苹果等都支持HTML 5
  • IDEA写爬虫,配jsoup

    环境变量配了 jdk的lib目录下也加了jsoup的jar包 返回IDEA还是没有 点击左上角的File进Project Setting SDKs 选择自己的jdk文件 在右侧点击 把jar包导进来
  • K8S 安装步骤

    K8S 安装步骤 一 为每台机器安装docker 1 安装docker 1 1 卸载旧版本 sudo yum remove docker docker client docker client latest docker common do
  • 【游戏开发】[用代码创建unity5.X的动画状态机]

    不废话 上代码 可能有的人 会质疑 这不是editor的功能吗 是的 但是这个允许在运行时候使用 你们跟一下代码看看继承于哪里就知道了 using UnityEngine using System Collections using Sys
  • JAVA-时间日期格式转换

    第一种方式 获取当前时间然后按照指定格式转换成String类型 DateFormat dateFormat new SimpleDateFormat yyyy MM dd HH mm ss Calendar cal Calendar get
  • 【Shell牛客刷题系列】SHELL31 netstat练习3-输出每个IP的连接数

    该系列是基于牛客Shell题库 针对具体题目进行查漏补缺 学习相应的命令 刷题链接 牛客题霸 Shell篇 该系列文章都放到专栏下 专栏链接为 专栏 Shell 欢迎关注专栏 本文知识预告 本文复习了awk grep sort uniq命令
  • DEiT实战:使用DEiT实现图像分类任务(二)

    文章目录 训练 导入项目使用的库 设置随机因子 设置全局参数 图像预处理与增强 读取数据 设置模型 train py train dist py 定义训练和验证函数 训练函数 验证函数 调用训练和验证方法 运行以及结果查看 测试 完整的代码
  • win10 git bash 设置别名

    使用git挺久时间 每次输入需要敲入长命令已感费劲 zshell git 有不少别名 可以提高输入效率 从而寻找windows下设置 git bash 别名的方法 环境 git v2 22 0 win10 方法1 通过 profile 文件
  • 使用gtest做单元测试

    使用gtest做单元测试 文章目录 使用gtest做单元测试 1 用gtest写测试工程的大致流程 配置gtest头文件及库 gtest的相关概念 TEST与TEST F 断言 事件机制 参考 gtest是一个跨平台的 Liunx Mac
  • Pycharm 常用快捷键

    常用快捷键 快捷键 功能 Ctrl Q 快速查看文档 Ctrl F1 显示错误描述或警告信息 Ctrl 行注释 可选中多行 Ctrl Alt L 代码格式化 Ctrl Alt O 自动导入 Ctrl Alt I 自动缩进 Tab Shift
  • 【网络】多路转接——poll

    作者 一只大喵咪1201 专栏 网络 格言 你只管努力 剩下的交给时间 书接上文五种IO模型 select poll epoll poll 认识接口 简易poll服务器 poll的特点 epoll 认识接口 epoll原理 简易epoll服
  • CentOS7 安装Redis6过程详解

    CentOS7 安装Redis6过程详解 一 安装redis 1 下载Redis 2 解压 3 使用make编译 4 编译完成后在目录中执行make install安装redis服务 5 安装完成 二 设置redis后台运行以及远程连接 1
  • 华为OD机试 - 找车位(Java)

    题目描述 停车场有一横排车位 0代表没有停车 1代表有车 至少停了一辆车在车位上 也至少有一个空位没有停车 为了防剐蹭 需为停车人找到一个车位 使得距停车人的车最近的车辆的距离是最大的 返回此时的最大距离 输入描述 一个用半角逗号分割的停车
  • Zookeeper 基本数据模型

    介绍 ZooKeeper是一个树形结构 类似于前端开发中的tree js组件 ZooKeeper的数据模型也可以理解为linux unix的文件目录 usr local 每个节点都称为znode 它可以有子节点 也可以有数据 每个节点分为临
  • 正则表达式-分组与后向引用

    前文中 已经总结了正则表达式中的常用字符 次数匹配 位置匹配等 这篇文章中 我们来了解一下正则中的 分组 与 后向引用 什么是分组 什么是后向引用 我们慢慢聊 先来说说什么是分组 算了 思考了半天 我也不知道从何说起 先看个示例吧 根据示例