正则表达式进阶

正则表达式与匹配技术详解
本文深入探讨了正则表达式的应用,包括匹配日期、数字、字符串以及如何使用正则表达式进行复杂匹配。文章还介绍了正则表达式的各种选项、特性,如懒惰匹配、减少回溯和使用占有量词与原子组来优化性能。
捕获匹配结果,并为之命名
以下示例表示匹配日期表示中的年月日,并给他们命名。

giNamed capture
\b(?<year>\d\d\d\d)-(?<month>\d\d)-(?<day>\d\d)\b
Regex options:None
Regex flavors:.NET, PCRE 7, Perl 5.10, Ruby 1.9
\b(?'year'\d\d\d\d)-(?'month'\d\d)-(?'day'\d\d)\b
Regex options:None
Regex flavors:.NET, PCRE 7, Perl 5.10, Ruby 1.9
\b(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d)\b
Regex options:None
Regex flavors:PCRE 4 and later, Perl 5.10, Python


以下示例是匹配日期,并要求年份的后两位、月份、日子这三个数字要是一样的。目标字符串【2012-12-12】【2008-08-08】

Named backreferences
\b\d\d(?<magic>\d\d)-\k<magic>-\k<magic>\b
Regex options:None
Regex flavors:.NET, PCRE 7, Perl 5.10, Ruby 1.9
\b\d\d(?'magic'\d\d)-\k'magic'-\k'magic'\b
Regex options:None
Regex flavors:.NET, PCRE 7, Perl 5.10, Ruby 1.9

\b\d\d(?P<magic>\d\d)-(?P=magic)-(?P=magic)\b
Regex options:None
Regex flavors:PCRE 4 and later, Perl 5.10, Python




匹配字符串次数设置

  • 匹配一个数字100次,正则表达式:【\b\d{100}\b】
  • 匹配一个32-bit的十六进制数字,正则表达式:【\b[a-f]{1,8}\b】
  • 匹配一个可能带有字母"h"的十六进制数字,正则表达式:【\b[a-f0-9]{1,8}h?】
解释:
  • 【{n}】表示匹配前面的字符n次
  • 【{n, m}】m大于n,表示匹配前面的字符n次~m次
  • 【h?】等价于【h{0,1}】, 表示h不出现,或者出现一次。
  • 【{n, }】表示匹配前缀的字符可以出现n次到无穷次。
  • 【\d{1, }】等价于【\d+】,表示数字出现1到无穷次。
  • 【\d{0,}】等价于【\d*】,表示数字出现0到无穷次。


惰性匹配
前面介绍都是贪心匹配,比如【\d{3, 10}】表达式会贪心匹配数字字符。
惰性匹配是指尽量少匹配,惰性匹配的方法就是在表达式后面加上【?】,比如表达式【\d{3, 10}?】等价于【\d{3}】.
惰性匹配的典型应用是在html/XML代码解析过程中,比如要从<p>test1</p><p>test2</p>字符串中找到第一个p标签的内容。最容易想到的表达式就是【<p>.*</p>】,但是其实这是个贪心匹配,会匹配第一个<p>到最后一个</p>之间的内容。对应的惰性匹配表达式就是【<p>.*?</p>】,将会匹配第一个<p>与第一个</p>之间的内容。


减少不必要的回溯
这部分将介绍两个名词:占有量词(possessive quantifier)、原子组(atomic group).
假如我们利用贪心量词表达式【\b\d+\b】去匹配目标字符串【1234X】,
  • 【\b\d++】首先会匹配到【1234】,最后一个【\b】匹配失败;
  • 再将【\b\d++】回溯匹配到【123】,最后一个【\b】又匹配失败;
  • 再将【\b\d++】回溯匹配到【12】,最后一个【\b】又匹配失败;
  • 最后【\b\d++】回溯匹配到【1】,最后一个【\b】有匹配失败,最终失败返回。
从以上步骤我们可以看出,贪心匹配又有一个明显的性能缺陷就是它会不断的回溯直至失败。如果目标字符串很长,它就很耗时。
针对贪心匹配的缺陷,有两种解决方法:占有量词、原子组。
占有量词与贪心匹配相似,它会尽量匹配更多的字符。不同点就是当匹配失败时,它不会回溯,它只会在剩余字符串查找匹配结果。
原子组的效果与占有量词是一样的。

下面介绍它们的表示方法。以表达式【\d+】为例
  • 贪心匹配表达式:【\d+】
  • 占有量词表达式是在贪心表达式加上【+】,形如【\d++】,【*+】,【?+】
  • 原子组表达式形如【(?>regex)】,例如【(?>\d+)】


减少不必要的回溯

形式:【(?(1)then|else)

解释:

如果group1的内容被匹配,则接下来匹配then部分。如果group1部分没有匹配就匹配else部分。

在此说明group的概念,一个正则表达式中,每一对括号包含的内容称为一个group,第一个括号的内容称为group1,第二个称为group2.

举例:【(a)b(?(1)c|d)】将会匹配abc或者bd


从提供的引用来看,涉及到 Python 正则表达式在头歌平台的部分基础内容,包括`re.findall()`函数以及一些正则表达式元字符的运用。不过该引用未涵盖头歌平台 Python 正则表达式进阶内容。 通常 Python 正则表达式进阶内容可能会包含以下方面: - **高级正则表达式元字符**:例如`(?=...)`(正向前瞻断言)、`(?!...)`(负向前瞻断言)、`(?<=...)`(正向后瞻断言)、`(?<!...)`(负向后瞻断言)等。这些断言能让匹配在特定条件下进行,而不消耗字符。 - **分组与捕获**:正则表达式中的分组不仅可以用于将部分模式组合,还能通过捕获组来提取匹配的特定部分。例如`(...)`用于创建捕获组,`(?:...)`用于创建非捕获组。 - **正则表达式的编译**:使用`re.compile()`函数将正则表达式编译成一个模式对象,这样可以提高匹配效率,尤其是在需要多次使用同一个正则表达式时。 - **替换与分割**:`re.sub()`函数用于替换匹配的内容,`re.split()`函数用于根据正则表达式分割字符串。 以下是一些示例代码,展示上述部分进阶内容: ```python import re # 正向前瞻断言示例 text = "apple123 banana456" pattern = r'\w+(?=\d+)' result = re.findall(pattern, text) print(result) # 分组与捕获示例 text = "John: 25, Jane: 30" pattern = r'(\w+): (\d+)' matches = re.findall(pattern, text) for match in matches: print(f"Name: {match[0]}, Age: {match[1]}") # 正则表达式编译示例 pattern = re.compile(r'\d+') text = "abc123def456" result = pattern.findall(text) print(result) # 替换示例 text = "Hello, World! Hello, Python!" pattern = r'Hello' new_text = re.sub(pattern, 'Hi', text) print(new_text) # 分割示例 text = "apple,banana;cherry|date" pattern = r'[;,|]' result = re.split(pattern, text) print(result) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值