资讯动态

python-字符串全解(六):正则表达式-元字符与转义

发布时间:2026/10/18 6:14:28 来源:尧图企业网站定制
正则表达式作为一种有特殊含义的字符串一方面它必须遵循python字符串的规则另一方面它又有自己的一套规则。和字符串一样用一些特殊的字符表达特定的含义。比如用点号.来表示任意字符用*来表示0个或者多个重复。那既然这些字符都代表了特殊的含义那么如何表示这些字符本身呢我们都知道字符串中有转义字符例如用\n表示换行同样\n在正则表达式中也是换行的意思这在正则表达式中叫预定义字符所以我们之前在讲预定义字符的时候举了一个例子\n和\\n在正则表达式中都是换行的意思。如果你忘记了请参照之前的章节预定义字符。像这些在正则表达式中有特殊含义的字符我们称之为元字符。元字符是组成正则表达式的基本语法基石我们要写好正则表达式这些字符的含义必须牢记于心。元这个字在汉语中有根本本源的含义是构成事物的基础。我们现在有元素周期表元数据等但大体的意思没变所以元字符就是构成正则表达式基础语法的字符。既然这些字符在正则表达式中是元字符那么如果想表示字符串中的该字符的本来含义该怎么办呢我们借用了字符串中的概念转义。我们通过转义让元字符表示字符串中的含义转义和字符串中的形式是一样的例如要表示字符串中的点号.我们只需要在前面加上反斜杠就行形式为\. 。正则表达式中的元字符有不少接下来我们来详细介绍。10元字符元字符包含如下字符点号.星号*加号问号?左圆括号(右圆括号)左方括号[右方括号]左画括号{右花括号}管道符|脱字符^美元符号$反斜杠\。这些元字符我们在讲之前章节的语法中都提到了本章只是一个总结让大家明白如果字符串有这些字符如何用正则表达式匹配它们。其实答案很简单就是在这些字符前面加反斜杠\不论在什么场景下加反斜杠都不会错但是某些不引起歧义的场景下我们也可以不加。那么接下来我们来详细说明。10.1点号.星号*加号问号?这四个符号放在一起说因为它们都代表不确定性。点号.代表任何一个非换行的字符星号*代表前面的字符出现0次或者多次加号代表前面的字符出现1次或者多次问号代表前面的字符出现0次或者1次。接下来我们看代码import re a 1.25*3.14?\n5.374.18? b re.findall(r\d\.\d{2}\*\d\.\d{2}\?, a) c re.findall(r\d\.\d{2}\\d\.\d{2}\?, a) d re.findall(r\d[.]\d{2}[*]\d[.]\d{2}[?], a) e re.findall(r\d[\.]\d{2}[\*\]\d[\.]\d{2}[\?], a) print(b {}, c {}, d {}, e {}.format(b, c, d, e)) # 输出结果b [1.25*3.14?], c [5.374.18?], # d [1.25*3.14?, 5.374.18?], # e [1.25*3.14?, 5.374.18?]字符串a包含了这四个元字符因为在字符串中这几个字符就是普通字符所以我们直接写就可以了。b中我们用\d代表数字\. 代表点号\*代表星号用\?代表问号可以看到匹配到了字符串a的第一行c和b类似只是用\代表加号匹配到了a字符串的第二行。之前我们说过如果不会引起歧义这么元字符可以不转义而表示字符本身在字符类中的这四个元字符可以直接使用而不需要转义。如d所示我们将这四个字符方括号中表示字符类最后结果是匹配了a的两行。当然你仍然可以在字符类中使用转义如e所示但是效果和d一样只是显得复杂点。10.2左圆括号(右圆括号)左方括号[右方括号]左画括号{右花括号}这三种括号圆括号代表分组方括号代表字符类以及花括号代表重复次数。如果需要匹配这些括号本身需要在前面加\。看一下下面的代码import re a [apple]{pear}(peach) b re.findall(r\[\w\], a) c re.findall(r\{\w\}, a) d re.findall(r\(\w\), a) e re.findall(r[{[(]\w[])}], a) f re.findall(r[\{\[\(]\w[\]\}\)], a) g re.findall(r[{(})]\w[(){}], a) h re.findall(r[{([)]]\w[(){}], a) i re.findall(r[{(){]}]\w[(){}], a) #unbalanced parenthesis at position 5 #j re.findall(r[{[(])]]\w[(){}], a) k re.findall(r\[\w], a) k1 re.findall(r\{\w}, a) #k2 re.findall(r\(\w), a) print(b {}, c {}, d {}, e {}, f {}, g {}, h {}, \ i {}, k {}, k1 {} .format(b, c, d, e, f, g, h, i, k, k1)) # 输出结果b [[apple]], c [{pear}], # d [(peach)], e [[apple], {pear}, (peach)], # f [[apple], {pear}, (peach)], g [{pear}, (peach)], # h [], i [], k [[apple]], k1 [{pear}]上面字符串a包含了方括号花括号以及圆括号。b通过\[来匹配左方括号\]来匹配右方括号\w来匹配单词所以可以得到[apple]这样的结果。c和d的道理是一样的。e把左括号和右括号分别放在了字符类中仍然可以达到我们想要的效果可以看到e匹配到了三个结果。原因我们在10.1已经说了在字符类中这些都表示字符本身只要不引起歧义所以不需要转义也可以。在f中我们用了转义达到的效果是一样的。但是方括号是需要特别关注的因为字符类本身就是在方括号开始和结束的我们来看看e为什么可以成功。首先e中正则出现的第一个字符类是[{[(]我们可以看到字符类中包含的是左方括号这个在字符类中不会引起歧义原因是我们第一个左方括号代表字符类的开始然后遇到第二个左方括号因为要寻找字符类的边界右方括号所以这个第二个左方括号会当作是普通字符然后继续寻找寻找到了第一个右方括号因为字符类不允许嵌套立马结束所以此时第一个字符类中的左方括号会当作是普通字符不会产生歧义。第二个字符类和第一个又有不同因为第二个字符类第一个左方括号开始接下来就碰到了右方括号python会把紧跟随左方括号的右方括号当作一个普通字符。所以后面的})都会被当成普通字符直到碰到新的右方括号。g是字符类中没有方括号的情况结果也是符合预期的。h的问题是第一个字符类遇到第一个右中括号就结束然后剩下]a中没有两个括号连续的情况所以结果为空。i的问题和h类似第一个字符类中的右中括号和字符类开始的左中括号配成了一对导致剩下的字符}]被当作普通字符对待字符串a中没有匹配}]这两个连续字符的子串所以结果为空。j会产生错误根源是第一个字符类中遇到第一个右中括号会认为是字符类的边界此时后面紧跟右圆括号这个圆阔号是分组的标志在字符类外会当成元字符而不是普通字符最后曝出的错误是右圆括号)不匹配相比较h没有报错是因为h中圆括号都被包含在了字符类中。对于左括号肯定都是字符类分组量词的开始所以在字符类外必须转义而右括号的情况却不同如果右括号出现之前没有元字符左括号那么会被当作普通字符但是分组是一个例外kk1k2说明了这个问题k2的错误和j是一样的所以在字符类外面右圆括号也必须转义虽然我们认为不会引起歧义但是这确实是一个例外。当然说了这么多并不是为了让大家都熟记所有这些特殊场景如果你自己写正则对元字符进行显示转义是优先的写法但是你遇到其他人可能会有这种不转义的写法当你读到代码的时候知道这是怎么回事就行了。10.3管道符|脱字符^美元符号$反斜杠\管道符号|用来表示逻辑与脱字符^,在字符类外表示字符串或者行的开始在字符类内表示非美元符号$表示字符串或者行的结束反斜杠\用来表示转义有面必修跟符合转义的字符。这四个元字符脱字符^和反斜杠\在字符类内和字符类外都是元字符所以必须都要用显示转义其他两个字符在字符串内如果没有引起歧义可以不转义我们看下下面的代码import re a ^apple$pear|peach\\\n b re.findall(r\^\w\$, a) c re.findall(r\|\w\\, a) d re.findall(r[^]\w[$], a) e re.findall(r[|]\w[\\], a) f re.findall(r[\^]\w[\$], a) g re.findall(r[\|]\w[\\], a) h re.findall(r[^^\\$|]\w[^^\\$|], a) i re.findall(r[\^\\$|]\w[\^\\$|], a) #unterminated character set at position 6 #j re.findall(r[|]\w[\], a) #unterminated character set at position 0 #k re.findall(r[^]\w\$, a) #bad escape \g at position 1 #l re.findall(r[\g]\w\\, a) print(b {}, c {}, d {}, e {}, f {}, g {}, h {}, \ i {} .format(b, c, d, e, f, g, h, i)) # 输出结果b [^apple$], c [|peach\\], # d [^, |, \\, \n], e [|peach\\], # f [^apple$], g [|peach\\], # h [apple, pear, peach], i [^apple$, |peach\\]b和c都是用了转义将这四个元字符转义成普通字符所以从结果来看都匹配到了符合预期。d的结果其实很奇怪我们将^放到字符集中感觉应该和b的结果一样才对之前我们讲了^在字符类内也是元字符所以它将本来应该是字符类结束的右中括号]变成了普通字符直到遇到了下一个右中括号所以d的含义变成了要匹配单个字符这个字符不应该是]\w[$中的一个。所以我们得到了^, |, \, \n。e中字符类中的|成了普通字符我们在字符集中用\\代表\所以匹配到了正确的结果。g和e效果是一样的只是用反斜杠\对管道符|进行了转义。f在字符集中对脱字符^和美元符$进行了转义所以匹配到了^apple$。h并没有对脱字符转义但是通过两个脱字符达到了转义的效果只是正则的意思变为匹配的字符串前后不能包括这四个字符。i的意思刚好和h相反匹配的字符串前后必须出现这四个字符中的一个。j会报错因为字符集中直接写入反斜杠是作为元字符他转义了右中括号导致字符类找不到闭合的右中括号从而报错。k是因为脱字符将紧随其后的右中括号变成了普通字符到导致字符类找不到闭合的右中括号包括。这其实是d的出错版d没有出错是因为恰好找到了一个右中括号但是改变了正则表达式的本意。l会报错事因为\在字符类中是元字符它必然需要转义紧挨着它字符但是\g在正则表达式中没有定义所以会出错。讲到这里这一章就讲完了恭喜你已经完全学会了正则表达式的所有语法。但是关于正则表达式还没有结束。之前的章节我们只是粗略的讲了pythonn的正则函数下一章我们讲详细讲几个重要的函数并且总结一下内联标志和内联模式的对应。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑