正则表达式的分组

2023-05-16

一.概念

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

(\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:\d{1,3}匹配1到3位的数字,(\d{1,3}\.}{3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})。

不幸的是,它也将匹配256.300.888.999这种不可能存在的IP地址(IP地址中每个数字都不能大于255)。如果能使用算术比较的话,或许能简单地解决这个问题,但是正则表达式中并不提供关于数学的任何功能,所以只能使用冗长的分组,选择,字符类来描述一个正确的IP地址:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)。

理解这个表达式的关键是理解2[0-4]\d|25[0-5]|[01]?\d\d?,这里我就不细说了,你自己应该能分析得出来它的意义。

后向引用
使用小括号指定一个子表达式后,匹配这个子表达式的文本可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。

后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本。难以理解?请看示例:

\b(\w+)\b\s+\1\b可以用来匹配重复的单词,像go go, kitty kitty。首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b),然后是1个或几个空白符(\s+),最后是前面匹配的那个单词(\1)。

你也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?<Word>\w+)(或者把尖括号换成'也行:(?'Word'\w+)),这样就把\w+的组名指定为Word了。要反向引用这个分组捕获的内容,你可以使用\k<Word>,所以上一个例子也可以写成这样:\b(?<Word>\w+)\b\s+\k<Word>\b。

使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些:

表4.分组语法 捕获
(exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp) 匹配exp,不捕获匹配的文本
位置指定
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注释
(?#comment) 这种类型的组不对正则表达式的处理产生任何影响,只是为了提供让人阅读注释

我们已经讨论了前两种语法。第三个(?:exp)不会改变正则表达式的处理方式,只是这样的组匹配的内容不会像前两种那样被捕获到某个组里面。

位置指定
接下来的四个用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们用于指定一个位置,就像\b,^,$那样,因此它们也被称为零宽断言。最好还是拿例子来说明吧:

(?=exp)也叫零宽先行断言,它匹配文本中的某些位置,这些位置的后面能匹配给定的后缀exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如果在查找I'm singing while you're dancing.时,它会匹配sing和danc。

(?<=exp)也叫零宽后行断言,它匹配文本中的某些位置,这些位置的前面能给定的前缀匹配exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading。

假如你想要给一个很长的数字中每三位间加一个逗号(当然是从右边加起了),你可以这样查找需要在前面和里面添加逗号的部分:((?<=\d)\d{3})*\b。请仔细分析这个表达式,它可能不像你第一眼看出来的那么简单。

下面这个例子同时使用了前缀和后缀:(?<=\s)\d+(?=\s)匹配以空白符间隔的数字(再次强调,不包括这些空白符)。

负向位置指定
前面我们提到过怎么查找不是某个字符或不在某个字符类里的字符的方法(反义)。但是如果我们只是想要确保某个字符没有出现,但并不想去匹配它时怎么办?例如,如果我们想查找这样的单词--它里面出现了字母q,但是q后面跟的不是字母u,我们可以尝试这样:

\b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的单词。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为[^u]总是匹配一个字符,所以如果q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w*\b将会匹配下一个单词,于是\b\w*q[^u]\w*\b就能匹配整个Iraq fighting。负向位置指定能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:\b\w*q(?!u)\w*\b。

零宽负向先行断言(?!exp),只会匹配后缀exp不存在的位置。\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字。

同理,我们可以用(?<!exp),零宽负向后行断言来查找前缀exp不存在的位置:(?<![a-z])\d{7}匹配前面不是小写字母的七位数字(实验时发现错误?注意你的“区分大小写”先项是否选中)。

一个更复杂的例子:(?<=<(\w+)>).*(?=<\/\1>)匹配不包含属性的简单HTML标签内里的内容。(<?(\w+)>)指定了这样的前缀:被尖括号括起来的单词(比如可能是<b>),然后是.*(任意的字符串),最后是一个后缀(?=<\/\1>)。注意后缀里的\/,它用到了前面提过的字符转义;\1则是一个反向引用,引用的正是捕获的第一组,前面的(\w+)匹配的内容,这样如果前缀实际上是<b>的话,后缀就是</b>了。整个表达式匹配的是<b>和</b>之间的内容(再次提醒,不包括前缀和后缀本身)。

二.实际运用
现在网络上现在很流行的爬虫程序,其实就是根据正则表达式来对网页进行解析匹配获取有用信息分组并存储下来的.
像网页上最多的就是像<table>,<tr>,<td>之类的标签,而相对于我们用户而言,这些都是没有任意意义的,有意义的是其中所包含的值.如<a href="http://www.163.com">网易</a>我所所关心的就是其href属性当中的值,还有就是其文字结点的值.其它的对于我们来说没有任何意义.这就要运用到我们所说的正确表达式匹配了.
不过如果我们只是针对取某一个标签的结点值,我们可以通过javascript+DOM方法把他们取出来,不过要是不是一类而是要求全部内空当中去取,那样用DOM动态解析的方式就显着有时不好用了.
下同说一个我运用的实例吧
我有一个页面:

< p >  11-13    < a    href =/bj/11/109/4969873.html    target =_blank >  中介   -   3400元/3居   -   紫竹桥兵器大厦附近大三居   (紫竹院)    </ a >  
< p >  11-13    < a    href =/bj/11/104/4969872.html    target =_blank >  1200元/3居   -   出租上地三居室合住(免中介费)   (上地)    </ a >  
< p >  11-13    < a    href =/bj/11/114/4969866.html    target =_blank >  中介   -   2600元/2居   -   北太平庄43号院二居出租   (北太平庄)    </ a >  
< p >  11-13    < a    href =/bj/11/914/4969865.html    target =_blank >  400元/1居   -   单间独立卫浴免供暖费   (北七家)    </ a >  
< p >  11-13    < a    href =/bj/11/301/4969864.html    target =_blank >  中介   -   2400元/2居   -   东直门春秀路太平庄南里二居室出租   (东直门外三里屯工人体育馆)    </ a >  
< p >  11-13    < a    href =/bj/11/208/4969863.html    target =_blank >  中介   -   2400元/4居   -   出租定福家园新房四居室   (团结湖)    </ a >  
< p >  11-13    < a    href =/bj/11/214/4969862.html    target =_blank >  中介   -   2600元/3居   -   花家地北里三室一厅出租   (酒仙桥   将台路)    </ a >  
< p >  11-13    < a    href =/bj/11/209/4969859.html    target =_blank >  1300元/1居   -   十里堡华堂附近新公寓合租   (京广桥   红庙   八里庄)    </ a >  
< p >  11-13    < a    href =/bj/11/70/4969846.html    target =_blank >  中介   -   600元/3居   -   出租丰益桥西盛鑫家园4室2厅2卫精装修的房子(免收中介费   (丰益桥西盛鑫家园)    </ a >  
< p >  11-13    < a    href =/bj/11/901/4969844.html    target =_blank >  750元/3居   -   田园风光雅园3居中的一居室出租   (回龙观)    </ a >  
< p >  11-13    < a    href =/bj/11/1101/4969840.html    target =_blank >  350元/1居   -   找一女孩跟我合租   (亦庄)    </ a >  
< p >  11-13    < a    href =/bj/11/102/4969839.html    target =_blank >  中介   -   3400元/3居   -   出租知春里小区三居室   (北京大学)    </ a >  
< p >  11-13    < a    href =/bj/11/217/4969838.html    target =_blank >  1100元/3居   -   双井桥   三居   出租   (新装修的)合租   (双井)    </ a >  
< p >  11-13    < a    href =/bj/11/70/4969837.html    target =_blank >  中介   -   3500元/3居   -   丰台区兆丰园精装修房子一套低价出租   (玉泉路     吴家村)    </ a >  
< p >  11-13    < a    href =/bj/11/70/4969835.html    target =_blank >  中介   -   2900元/3居   -   我有一套长安新城精装修的三居室要出租   (青塔   大成路   长安新城)    </ a >  
< p >  11-13    < a    href =/bj/11/201/4969834.html    target =_blank >  中介   -   2200元/1居   -   房屋出租,北辰附近   (亚运村)    </ a >  


我现在要取出其中的链接和相应的关键描述字符,即从类似
<p> 11-13   <a   href=/bj/11/70/4969837.html   target=_blank> 中介   -   3500元/3居   -   丰台区兆丰园精装修房子一套低价出租   (玉泉路     吴家村)   </a>
中取出我们想要的信息,第一就是链接地址:/bj/11/70/496837.html;第二就是其描述信息:中介   -   3500元/3居   -   丰台区兆丰园精装修房子一套低价出租   (玉泉路     吴家村) 
 
现在我们来分析下我们所取字符的共同特征,简单总结一下分为以下几个部分
1.他们都是以<a href=打头,以</a>结尾.
2.在href属性之后有可能还有其他的属性标签,如class,等其它相关的属性.

方向确定我们就可以确定着手写正则式了
首先满足第一条件头就为<a\s+href=;就是这样,很简单吧,同样,末尾为</a>也可以直接写
应该说现在已经可以正常匹配了,不过他匹配了一个整个的<a>标签,不是我们所想要的,我们只是想要其中的部分
所以还需要继续修改,因为我们要在一个标签中去取两个部分,一个链接和描述文字,其最好的方法就是把他们放在一个分组当中,待我们使用时可以直接使用,关于建立分组,前面的资料说的很清楚.为了直观,我们采用自定义分组,即(?<分组名>)格式
一起组织起来就成了我们想要的.


( ?<=< a\s + href = ( ?< link > . *? ( ?= \starget = )). *?> ( ?< content > . *? )( ?=</ a > )

因为时间的关系,其中分析过程略的较多,不过具体大体思路就像如上所说.只不过具体的问题具体分析.



转载于:https://www.cnblogs.com/symbol441/archive/2007/11/13/957950.html

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

正则表达式的分组 的相关文章

  • No valid host was found. There are not enough hosts available

    root 64 dell PowerEdge T30 nova boot flavor m1 tiny image cirros nic net id 61 c2943fac a910 4cf6 b021 e8ab321965c9 secu
  • 校园网频繁断线、连不上网etc.

    这篇记录一下 Windows 下安装完 虚拟机 之后 xff0c 校园网 xff08 和其他网络 xff09 断线 xff0c 甚至无法连接到网络的情况 背景 xff1a 新装的系统 xff0c 网卡驱动什么的也都是刚装好的 xff0c 虚
  • JavaScript 笔记(3) -- JSON

    JavaScript JSON JavaScript Object Notation 是一种轻量级的数据交换格式 JSON 是用于存储和传输数据的格式JSON 通常用于服务端向网页传递数据 JSON 使用 JavaScript 语法 xff
  • 【转载】Notepad++使用技巧

    一 安装notepad 43 43 notepad 43 43 的下载 安装非常easy 下一步下一步 xff0c 所有选项都默认就可以安装好 但有几点需要注意 截止到写这篇博文 xff0c notepad 43 43 的最新版本为7 5
  • 0.1+0.2为什么不等于0.3

    首先 xff0c 对于不同的进制数值系统 xff0c 分母为多少时能除干净 xff1f 答案是当以前进制数的质因子为分母时 xff0c 以十进制为例 xff0c 它的质因子为2 5 xff0c 因此1 2 1 4 1 5 1 8和 1 10
  • git tag

    git tag的用法 git的tag功能 git 下打标签其实有2种情况 轻量级的 xff1a 它其实是一个独立的分支 或者说是一个不可变的分支 指向特定提交对象的引用带附注的 xff1a 实际上是存储在仓库中的一个独立对象 xff0c 它
  • 对web前端这门课程的期望

    对于这门课程 xff0c 我只希望我能过就行 xff0c 因为我将来可能不会从事着方面的工作 xff0c 但为了丰富自己的知识 xff0c 我还是觉得要认真的对待每一门学科 xff0c 这一门也不例外 xff0c 我希望我可以学的尽量好一点
  • ArcEngine安装并注册后应用程序无法使用toc等控件的解决办法

    安装了ArcEngine xff0c 并且用ecp注册过 但当放置toolbarcontrol TOCControl等控件在窗体上时 xff0c 提示 this control require an esri designer licens
  • Debian中安装使用sudo命令

    Debian中安装使用sudo命令 sudo可以让非root用户具有管理员的权限 xff0c 安装好的Debian后还不能使用sudo 需要使用root用户登陆后安装sudo命令 span style color 000102 span s
  • linux breakpad 编译,linux 平台编译googlebreakpad并测试 demo

    Linux googlebreakpad 编译 1 下载源码 源码包括两部分 xff0c 分为依赖库和 breakpad xff0c 网址一般会被屏蔽 xff0c 需要墙一下 另 xff0c 编译器需要支持 c 43 43 11 我用的gc
  • 233

    include lt bits stdc 43 43 h gt define reg register int define il inline define fi first define se second define mk a b
  • 再探容斥好题——ROOK

    这个时候考过 xff1a 安师大附中集训 Day2 当时看shadowice1984的做法 xff0c 但是没有亲自写 xff0c xff0c xff0c 雅礼集训考试的时候鼓捣半天 xff0c 被卡常到80pts xff0c 要跑9s 卡
  • CF908G New Year and Original Order

    CF908G New Year and Original Order gzz讲过 xff0c 可我到今天还是不会 有点trick的数位DP 比较显然的思路是 xff0c 考虑所有数中排序后每一位的贡献 cnt i x 表示S 1 S x 第
  • 本地在不安装Oracle的情况下安装PLSQL客户端

    本文解决问题 xff1a 通常在本地安装PLSQL后 xff0c 如果本地没有安装Oracle数据库的话 xff0c PLSQL是不能使用的 xff0c 输入远程数据库登录信息会提示 xff1a Oracle Client没有正确安装 这个
  • Ubuntu的中文乱码问题

    目标 xff1a 使系统 服务器支持中文 xff0c 能够正常显示 1 首先 xff0c 安装中文支持包language pack zh hans xff1a sudo apt get install language pack zh ha
  • Python argparse 处理命令行小结

    Python argparse 处理命令行小结 1 关于argparse 是python的一个命令行解析包 xff0c 主要用于处理命令行参数 2 基本用法 test py是测试文件 xff0c 其内容如下 import argparse
  • 分布式系统心跳协议的设计

    分布式系统心跳协议的设计 应用层心跳必不可少 xff1a 1 操作系统崩溃导致机器重启 没有机会发送 FIN 分节 2 服务器硬件故障导致机器重启 也没有机会发送 FIN 分节 3 并发连接数很高时 操作系统或进程如果重启 可能没有机会断开
  • malloc vs memset

    malloc vs memset OS内存分配过程如下 xff1a 用户态程序使用malloc接口 xff0c 分配虚拟地址 用户程序访问该虚拟地址 xff0c 比如memset 硬件 xff08 MMU xff09 需要将虚拟地址转换为物
  • c++ rvo vs std::move

    c 43 43 rvo vs std move To summarize RVO is a compiler optimization technique while std move is just an rvalue cast whic
  • linux du

    1 显示当前目录及子目录每个文件占用的块数量 du 2 显示当前目录占用的块数量 du s 3 查看当前目录占用空间啊大小 xff08 空间大小 61 块数量 块大小 xff09 du sh 4 查看当前目录各个文件占用空间大小 du sh

随机推荐

  • python绘制散点图入门

    import matplotlib pyplot as plt x values 61 list range 1 1001 y values 61 x 2 for x in x values plt scatter x values y v
  • linux 配置 l2tp-client

    1 安装yum源 yum install epel release 1 安装xl2tpd和ppp yum y install xl2tpd ppp 3 配置xl2tpd conf xff0c 原始的xl2tpd conf里面有 lns de
  • ros开启快速转发模式

    RB CCR设备开启FastTrack ip firewall filter add chain 61 forward action 61 fasttrack connection connection state 61 establish
  • ROS的脚本多拨

    ros设置单网卡拨多ADSL 使用vrrp 有些版本有问题 xff0c 使用5 2破解版本测试成功 1 创建100个vrrp 并绑定到wan口下 for i from 1 to 100 do 61 interface vrrp add co
  • zabbix4.0 相关的拓扑图及centos的虚拟配置

    zabbix的拓扑图相关资料 https blog 51cto com qicheng0211 1591073 zabbix配合 grafana zabbix 安装好后 参考 grafana 官方文档 https grafana com g
  • 通过TCP协议发送DNS请求

    通过TCP协议发送DNS请求的方法 文章出处 xff1a http www bingtech net wordpress 2011 04 233 下载dnsapi dll文件 然后到Google xff0c 搜索 替换系统文件 replac
  • PLC实现积分的计算方法

    以电机运行转速来计算电机运行圈数为例 在PLC中定义定时器中断 xff0c 中断时间设置为200ms 转载于 https www cnblogs com chenpan6227 p 11558647 html
  • PLC中相关量的斜坡控制

    转载于 https www cnblogs com chenpan6227 p 11558750 html
  • PLC中m法计算电机转速

    转载于 https www cnblogs com chenpan6227 p 11558715 html
  • oauth2.0+jwt 源码探究之旅

    oauth2 0协议是一种对外开放式协议 xff0c 主要用于第三方登录授权 例如 xff1a 在豆瓣官网点击用qq登录 以及微信的授权都是基于oauth2 0协议做的 oauth2 0的认证流程 xff08 A xff09 用户打开客户端
  • 读取 appsettings.json

    Appsettings json 配置 xff1a 个配置文件就是一个json文件 xff0c 并且是严格的json文件 xff0c 所有的属性都需要添加 引号 下图是一个常规的代码示例 xff1a 34 UrlString 34 34 U
  • OVN学习整理

    部署OVN网络拓扑 OVN 安装软件包 etc yum repos d CentOS OpenStack ocata repo yum list installed grep openvswitch openvswitch x86 64 1
  • 关于python写文件时的回车符

    测试环境Windows 回车符是0x0D和0x0A俩个字符 xff0c 在python中记为 39 r n 39 写文件时 xff0c 如果文件打开格式为 39 w 39 xff0c 39 n 39 就按照0D 0A写入了文件 xff0c
  • 《对软件工程课程的期望》

    自我介绍 xff1a 各位老师 xff0c 同学大家好 我是软件三班 李德帅 xff0c 大三了我希望通过这学期学习软件工程这门课 xff0c 拓展丰富自己的知识领域 xff0c 提升自己的对软件编程的思维和素质 xff0c 并且还要在与小
  • 软件工程概论作业1

    1需要网站系统开发需要掌握的技术 1 gt html与css网页开发基础 2 gt jsp语言 3 gt javaBean技术 4 gt servlet技术 5 gt 数据库的操作技术 2本次课堂测试的程序源代码 1 xff09 登陆页面
  • lisp填写明细表对话框_中望机械绘图中,明细表功能的试用技巧

    在机械设计过程中 xff0c 明细表 即 BOM表 是CAD设计图纸中的重要组成部分 xff0c 它包含了图纸中所有零件的类型 序号 名称 材料 代号 规格 数量以及重量等信息 xff0c 是指导物流部门和生产部门采购的关键文件 xff0c
  • Ubuntu16.04 中文乱码问题解决

    Ubuntu16 04 中文乱码问题解决 要适配一个服务 xff0c 用了mysql5 7的版本 xff0c 最新的Ubuntu适配起来头秃 xff08 直接用mysql8 0又出现jdbc接口修改的问题 xff09 xff0c 所以直接切
  • Centos 安装 kubectl kubelet kubeadm

    cat lt lt EOF gt etc yum repos d kubernetes repo kubernetes name 61 Kubernetes baseurl 61 https mirrors aliyun com kuber
  • 51单片机 中断控制蜂鸣器

    51单片机 中断控制蜂鸣器 单片机通过使用外部中断控制蜂鸣器 include lt reg51 h gt define uint unsigned int define uchar unsigned char 定义蜂鸣器连接的引脚 sbit
  • 正则表达式的分组

    一 概念 分组 我们已经提到了怎么重复单个字符 xff08 直接在字符后面加上限定符就行了 xff09 xff1b 但如果想要重复一个字符串又该怎么办 xff1f 你可以用小括号来指定子表达式 也叫做分组 xff0c 然后你就可以指定这个子