python-字符串全解(六):正则表达式-逻辑运算或

在上一章我们提到过,正则表达式没有专门的逻辑与(&)非(!)运算,因为顺序的正则表达式字符就是与运算,例如正则表达式r'abc',这里面的含义就是有一个字符串,需要第一个字符是a且第二个字符是b且第三个字符是c,这本身就是一个与(&)运算,只是不是通过显式的符号完成。同样的非,我们有负向先后行断言(?!),(?<=)来确定前面的或者后面不是某个字符或者字符串,还有就是在字符类中我们用^来说明当前字符不能出现在括号中,例如\^abc表示当前字符不能是abc中的一个。这样前中后刚好凑齐了逻辑非!。这三种情况都很详细的讲解了,之前我们简单的提到或|运算符,本章我们详细的讲解一下。

9逻辑运算或(|)

或的含义和python语言中的or是一个意思,表示两个选择或者多个选择,只要符合其中一个条件即可,在正则表达式中就是可以用一个正则表达式表示多种组合,要是没有或,我们可能就需要多写几个正则表达式了,这样无疑做了很多重复的工作。接下来,我们来详细说一下逻辑或的应用场景。

9.1整个正则匹配其中一个

就是用|将正则表达式分为两个或者多个部分,只需要匹配其中某个部分即可。看下面的代码:

复制代码
import re
import time
a = "abc efg hij"
b = re.findall(r"abc|efg", a)
c = re.findall(r'abc|efg|hij', a)

print("b = {}, c = {}".format(b, c))
# 输出结果:b = ['abc', 'efg'], c = ['abc', 'efg', 'hij']

b中我们用|连接abc和efg,意思是只要匹配abc或者efg中任何一个子串都满足要求,可以看到结果我们得到了abc和efg两个结果。c是匹配abc,efg和hij任何一个子串都满足要求,结果便是abc,efg,hij。

9.2在分组中匹配其中一个

在分组中使用或,或的作用范围只是在分组内,我们看一下下面的代码:

python 复制代码
import re
a = "abc21efg123hij111"
b = re.findall(r"(?:abc|efg)\d+", a)
c = re.findall(r'(?:abc|efg|hij)\d+', a)

print("b = {}, c = {}".format(b, c))
# 输出结果:b = ['abc21', 'efg123'], 
# c = ['abc21', 'efg123', 'hij111']

我们用(?:...)表示不捕获分组内容,让findall返回完整的正则匹配内容,可以看到逻辑或|只是限制在分组内,对于b来讲只要满足abc后面跟数字或者efg后面跟数字,都符合正则表达式的要求,所以得到了abc21和efg123。c也是同样的意思是,只是多了一个选择。

如果我们不使用括号,则逻辑或|的作用域会扩展到整个正则表达式,我们看下面的例子:

python 复制代码
import re
a = "abc21efg123hij111"
b = re.findall(r"abc|efg\d+", a)
c = re.findall(r'abc|efg|hij\d+', a)

print("b = {}, c = {}".format(b, c))
# 输出结果:b = ['abc', 'efg123'], 
# c = ['abc', 'efg', 'hij111']

b的结果来看,我们需要寻找满足abc或者efg\d+这样的子串,而不是满足abc\d+或者efg\d+的子串,这说明失去了分组,逻辑或|便会作用于全局。c的效果也是一样,只有最后一个匹配带了数字。

9.3 和量词组合

在9.2的第一个例子中,我们只是将逻辑或|放在分组中,此时如果在分组外面加量词,就会有排列组合的效果,我们看一下下面的代码:

python 复制代码
import re
a = "abcefg123efgabchij123efghij111"
b = re.findall(r"(?:abc|efg)+", a)
c = re.findall(r'(?:abc|efg|hij)+', a)
d = re.findall(r"(?:abc|efg)+?", a)
e = re.findall(r'(?:abc|efg|hij)+?', a)
print("b = {}, c = {}, d = {}, e = {}".
      format(b, c, d ,e))
# 输出结果:b = ['abcefg', 'efgabc', 'efg'], 
# c = ['abcefg', 'efgabchij', 'efghij'], 
# d = ['abc', 'efg', 'efg', 'abc', 'efg'], e
# = ['abc', 'efg', 'efg', 'abc', 'hij', 'efg', 'hij']

b在分组外面加了一个+,我们看到abcefg和efgabc都会被匹配到,原因是+是贪婪算法,字符串匹配到abc的时候,会继续匹配,这时候efg也能匹配,所以会匹配出abcefg的结果,同样,后续字符串中efg被匹配到,可以继续匹配,匹配到了efgabc。c也一样,只是c可以匹配三个的组合,例如匹配到了efgabcchij。d和e只是在+后面加了?,表示非贪婪匹配,所以我们看到没有匹配到组合,只需要匹配到分组中的任何一个就算匹配成功。

当然,如果你要匹配固定次数的组合,可以用{n}来代替+,这样可能还不能满足业务需求,例如你需要abc,efg,hig这三个组合中的任意两个组合,并且并不能是两个相同的组合在一起,例如不能出现abcabc,efgefg这样的情况,只是用固定次数还不能满足,这还需要用到前面讲到的前后相断言。我们看一下下面的代码:

python 复制代码
import re
a = "abcefg|abchij|abcabc|hijhij|efghij|efgefg"
b = re.findall(r'''(?x)(?:abc(?!abc)|
               efg(?!efg)|hij(?!hij)){2}''', a)

print("b = {}".
      format(b))
# 输出结果:b = ['abcefg', 'abchij', 'efghij']

可以看到字符串a是abc,efg,hij这三个子串的任何组合,中间用|分割,记住这个在字符串中只是普通的字符|。b中首先我们用了全局的详细模式,表明这个正则表达式忽略换行,回车,tab,空格等,所以我们把正则分成了两行。然后我们在abc后面面用了负向先行断言(?!abc),表明abc的后面不是能是abc,同样的,efg的后面不能是efg,以及hij的后面不能是hij,通过这种断言,我们会过滤到abcabc,efgefg,hijhij这种两个重复的情况,可以看到结果b也确实如此,可以看到通过组合正则语法,我们可以写出强大实用的功能。

9.4字符类中的或|

如果你在字符类中写了或|,那么这个字符将变成普通字符,而不是逻辑或。原因是在字符类中的每个字符都是或的关系,所以没必要再加一个或的运算符,所以|会自动被当成普通字符。看一下下面的代码:

python 复制代码
import re
a = "a1|2c2|3\\3"
b = re.findall(r'[abc|]\d', a)
c = re.findall(r'[abc\|]\d', a)
print("b = {}, c = {}".format(b, c))
# 输出结果:b = ['a1', '|2', 'c2', '|3'],
# c = ['a1', '|2', 'c2', '|3']

b中我们在字符类中加了|,我们可以看到结果中有|2,|3,所以在字符类中,|就是一个普通字符,在c中用反斜杠做了转义,效果和b是一样的。所以不论你加不加反斜杠,|在字符类中都只代表自己。

到这里这一章就结束了,这一章没什么新的内容其实,只是将之前学到的内容在稍微的复杂化一下,在下一章中,我们将会讨论元字符,这也不是什么新的内容,我们一直在用,只是没有明确的说明。

相关推荐
Thinker QAQ1 小时前
并发编程(九):BlockingQueue 与 Channel——语言层的原子性、可见性与有序性
java·python·go·并发编程·channel·blockingqueue·message passing
道满科技1 小时前
Function Calling 参数总出错?只修参数就行
linux·windows·python
霸道流氓气质2 小时前
RAG 可观测性与生产监控实战:四层遥测模型、五大仪表盘与 OpenTelemetry 全链路追踪的 Java 生产级实现
java·人工智能·python
ch6234 小时前
《AI 辅助编程实战:从零跑通一个 Excel 报表生成脚本的踩坑与复盘》
人工智能·python
import_random5 小时前
[python]conda和pip(区别和联系2)
python
Aurorar0rua5 小时前
CS50 x 2024 Notes Python - 01
开发语言·python·学习方法
用户6602676118795 小时前
备注接口返回成功,数据库却没变:怎样限定一次修复的范围?
python
Dumbness5 小时前
用 Python + UI Automation 读写微信 PC 版:一个群消息自动回复程序的实现与踩坑
python
艺杯羹5 小时前
Windows跨平台编码地雷全解:从GBK静默崩溃到内核级原子写入防御
人工智能·python·桌面客户端