python正则表达式的基本语法

2020年5月23日 / 35次阅读 / Last Modified 2020年9月7日
re模块

python中的正则表达式,与其它编程语言所支持的正则表达式,在语法上有许多都是相同的,这个给自己做一个简单的总结,以便以后查阅。

正则表达式中常用的metacharacter
正则表达式中常用的metacharacter

注意\w\s\d\b对应的\W\S\D\B是相互取反的意思。

注意python中还有\A和\Z来匹配开始和结束

重复

在正则表达式中表示重复的方法
在正则表达式中表示重复的方法

贪婪还是懒惰?

python的re模块默认执行贪婪匹配模式,即在符合正则表达式语义的情况下,尽可能多的匹配长的字串。我们也可以选择懒惰模式。

设置懒惰匹配模式
设置懒惰匹配模式

设置懒惰匹配模式,就是多加一个?号。

>>> re.search('a{2,6}?','aaaaab')
<re.Match object; span=(0, 2), match='aa'>
>>> re.search('a{2,6}','aaaaab')
<re.Match object; span=(0, 5), match='aaaaa'>
>>> re.findall('a.*?b', 'aabab')
['aab', 'ab']
>>> re.findall('a.*b', 'aabab')
['aabab']
>>>
>>> re.findall('a.*?b', 'aab')
['aab']
>>> re.findall('a.*?b', 'aaaaab')
['aaaaab']

注意以上示例代码,a.*?b是懒惰模式,但是为什么没有匹配出ab,而是把所有的a都匹配出来了呢?

简单地说,因为正则表达式有另一条规则,比懒惰/贪婪规则的优先级更高:最先开始的匹配拥有最高的优先权——The match that begins earliest wins。

转义\

  • \w\s\b\d等已经是转义的了,注意有可能需要在表达式字符串前加上r;
  • ^$*+?.等,如果要匹配这些符号,使用backslash,\^\$\*\.\?;
  • 字符集合[]的方式,[$*^+?.],^不在最开始就行,或者用\^;

字符集合[]

表示匹配[]中的任意一个符号,用[^]来取它的反义,也可在字符集合中对部分特殊字符进行转义匹配,入上一段描述。

[abcde],匹配abcde任意一个符号;

[^abcde],匹配任意一个不是abcde的符号;^如果不在最前面,就没有特别的含义;

[(^$*?.)-],匹配这些特殊字符,不用转义;

[a-zA-Z0-9],匹配范围;[-a],匹配-或a;[a\-z],此时-不再表示范围,仅仅是它自己;

[](){}[],[()[\]{}],匹配括号;

分支|

多个规则,用|符号来分开。

>>> re.findall('\d+|\w+|\$+','123abc$$$')
['123', 'abc', '$$$']

A|B, where A and B can be arbitrary REs, creates a regular expression that will match either A or B. An arbitrary number of REs can be separated by the '|' in this way. This can be used inside groups (see below) as well. As the target string is scanned, REs separated by '|' are tried from left to right. When one pattern completely matches, that branch is accepted. This means that once A matches, B will not be tested further, even if it would produce a longer overall match. In other words, the '|' operator is never greedy. To match a literal '|', use \|, or enclose it inside a character class, as in [|].

分支不仅可以在[]中使用,还可以在()中使用,威力更大。[]中是符号集,()中是pattern集。

分组()

分组的作用,除了能够通过Match对象的group()和groups()函数来获取整个匹配串以及各个分组所匹配的子串之外,还可以对子表达式进行整个的操作,比如重复。

>>> rt = re.search('(\d+)(\w+)(\$+)','123abc$$$')
>>> rt.groups()
('123', 'abc', '$$$')
>>> rt = re.search('(\d)+(\w+)(\$+)','123abc$$$')
>>> rt.group()
'123abc$$$'
>>> rt.groups()
('3', 'abc', '$$$')

命名分组(?p<name>)

上面简单的分组采用数字编号命名,默认从1开始,我们还可以自定义分组的名称。

>>> rt = re.search('(?P<number>\d+)==(?P<letter>[a-zA-Z]+)', '123==abc')
>>> rt.group()
'123==abc'
>>> rt.group(1)
'123'
>>> rt.group(2)
'abc'
>>> rt.group('number')
'123'
>>> rt.group('letter')
'abc'

反向引用

也有人说成后向引用(backreference)。正则表达式的匹配是从左到右进行的,反向(或后向),就是到左边去的意思。\number的方式,可以直接引用一个左边已经匹配的分组,number是分组号,默认从1开始,直到99.

For example, (.+) \1 matches 'the the' or '55 55', but not 'thethe' (note the space after the group). This special sequence can only be used to match one of the first 99 groups.

\b(\w+)\b\s+\1\b,可以用来匹配重复的单词,像go go, 或者kitty kitty。

当然也可以反向引用命名分组,语法为 (?P=name)

>>> rt = re.search('(?P<num>\d+)==(?P=num)', '123==123')
>>> rt.group()
'123==123'
>>> rt.group(1)
'123'
>>> rt.group('num')
'123'
>>> rt.group(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: no such group

-- EOF --

本文链接:https://www.pynote.net/archives/1970

留言区

《python正则表达式的基本语法》有2条留言

电子邮件地址不会被公开。 必填项已用*标注

  • 麦新杰

    分组()的用途,除了groups之外,在分组内使用|,或者对整个分组+*?,都很常见。 [回复]

  • 麦新杰

    关于back reference,并不是在右边使用与左边一样的re,而是右边完全等于左边。 [回复]


前一篇:
后一篇:

More


©Copyright 麦新杰 Since 2019 Python笔记

go to top