Search This Blog

Python 正则表达式

语法表

语法说明表达式实例完整匹配的字符串
字符
一般字符匹配自身abcabc
.匹配任意除换行符“\n”外的字符。
在DOTALL模式中也能匹配换行符。
a.cabc
\转义字符,使后一个字符改变原来的意思。
如果字符串中有字符*需要匹配,可以使用\*或者字符集[*]。
a\.c
a\\c
a.c
a\c
[...]字符集(字符类)。对应的位置可以是字符集中任意字符。
字符集中的字符可以逐个列出,或者给出范围,如[abc]或
[a-c]。第一个字符如果是^则表示取反,如[^abc]表示不是
abc的其他字符。
所有的特殊字符在字符集中都失去其原有的特殊含义。在字
符集中如果要使用 ]、-或^,可以在前面加上转义字符(\),
或把 ]、-放在第一个字符,把^放在非第一个字符。
a[bcd]eabe
ace
ade
预定义字符集(可以写在字符集[...]中)
\d数字:[0-9]a\dca1c
\D非数字:[^\d]a\Dcabc
\s空白字符:[<空格>\t\r\n\f\v]a\sca c
\S非空白字符:[^\s]a\Scabc
\w单词字符:[A-Za-z0-9]a\wcabc
\W非单词字符:[^\w]a\Wca c
数量词(用在字符或(...)之后)
*匹配前一个字符0或无限次。abc*ab
abccc
+匹配前一个字符1次或无限次。abc+abc
abccc
?匹配前一个字符0次或1次。abc?ab
abc
{m}匹配前一个字符m次。ab{2}cabbc
{m,n}匹配前一个字符m至n次。
m和n可以省略:若省略m,则匹配0至n次;若省略n,则匹
配m至无限次。
ab{1,2}cabc
abbc
*?, +?, ??
{m,n}?
使*, +, ?, {m,n}变成非贪婪模式abc{2,4}?abcc
边界匹配(不消耗待匹配字符串中的字母)
^匹配字符串开头。
在多行模式中匹配每一行的开头。
^abcabc
$匹配字符串末尾。
在多行模式中匹配每一行的末尾。
abc$abc
\A匹配字符串开头(对多行也仅匹配第一行开头)。\Aabcabc
\Z匹配字符串末尾(对多行也仅匹配最后一行末尾)。abc\Zabc
\b匹配\w和\W之间的字符。\bfoo\bfoo
bar foo bar
(foo)
foo2 (not matched)
\B匹配\w字符,但是不位于单词的开头或结尾。py\Bpython (matched)
py 3 (not matched)
逻辑、分组
|代表左右表达式任意匹配一个。
总是先尝试匹配左边的表达式,一旦成功则跳过匹配
右侧的表达式。如果 | 未被包括在 () 中,
则它的范围是整个正则表达式。
abc|defabc
def
(...)被括起来的表达式将作为分组,从表达式左边开始每遇到一
个分组的左括号 '(' ,编号+1.
另外,分组表达式作为一个整体,可以后接数量词。
表达式中的 | 仅在该组中有效。
(abc){2}
a(123|456)c
abcabc
a456c
(?P<name>...)分组,除了原有的编号外再额外指定一个别名(name)(?P<id>abc){2}abcabc
\<number>引用编号为<number>的分组匹配到的字符串。(\d)abc\11abc1
5abc5
(?P=name)引用别名为<name>的分组匹配到的字符串。(?P<id>\d)abc(?P=id)1abc1
5abc5
特殊构造(不作为分组,即不增加分组号)
(?:...)(...)的不分组版本(?:\d)(\d)abc\112abc2 (matched)
12abc1 (not matched)
(?#...)#后为注释内容,不形成匹配模式(?#comment)abcabc
(?=...)之后的字符串需要匹配表达式中的内容。
不消耗字符串内容。
abc(?=123)abc123 (matched)
匹配结果为 abc,
而不是 abc123。
abc12 (not matched)
(?!...)之后的字符串不是表达式中的内容,才匹配。
不消耗字符串内容。
abc(?!123)abc123 (not matched)
abc12 (matched)
匹配结果为 abc,
而不是 abc12。
(?<=...)之前的字符串需要匹配表达式中的内容。
不消耗字符串内容。
(?<=123)abc123abc (matched)
(?<!...)之前的字符串不是表达式中的内容,才匹配。
不消耗字符串内容。
(?!123)abc12abc (matched)
(?(id/name)
yes-pattern|
no-pattern)
类似C语言中的三元操作符(condition ? x : y),此处的含义
即当第id个分组或者名称为name的分组匹配到结果的时候
就采用yes-pattern,否则采用no-pattern,
其中no-pattern可以省略
(<)?(\w+@\w+(?:\.\w+)+)(?(1)>)<user@host.com>
user@host.com
---------------------------
<user@host.com
(not matched)

Python测试

Python中的正则表达式库为 re 。而常用的函数如下
  • compile
  • match
  • search
其中compile函数负责根据生成正则表达式生成相应的匹配模式,而matchsearch函数则根据匹配模式对目标字符串进行匹配。matchsearch的区别在于match是从字符串的开头匹配,相当于对匹配模式强制实施了\A,而search可以从字符串的任意位置匹配正则表达式。
import re

pattern = re.compile(r'world')
match1 = pattern.match('hello, world!')
match2 = pattern.search('hello, world!')

if match1:
    print(match1.group())
else:
    print("No match")

if match2:
    print(match2.group())
else:
    print("No match")
输出结果如下:
No match
world

Raw string

注意到上面的例子中声明pattern时使用了如下的方式 pattern = re.compile(r'world'),其中的 r'...' 表示字符串为 raw string,即不对反斜杠 (\) 做转义处理。例如:r'\n' 表示的正是两个字符 \n 的组合,而如果不声明为raw string的话 '\n' 表示的就是换行符。Raw string的最大好处在于声明正则表达式时可以简化书写。举例说明如下:
pattern1 = re.compile('\\w') # 需要第一个反斜杠对第二个反斜杠转义
pattern2 = re.compile(r'\w') # 反斜杠就是其本来的含义,因此无需两个

综合测试

结合前面的语法表,此处给出一个简单的综合测试案例。要求是从字符串中筛选出电子邮箱地址。实现的方式如下:
(<)?(\w+@\w+(?:\.\w+)+)(?(1)>)
用到的语法包括 \w, +, (?:...), (...), ?, (?(id) yes-pattern | no-pattern)
分析:我们知道邮箱的格式一般为 xxx@yyy.zzz
首先关注以上正则表达式的中间部分 (\w+@\w+(?:\.\w+)+)@前的\w+表示至少有一个字母或数字,指代了xxx部分;而@后的\w+指代了yyy部分;(?:\.\w+)+表明了.zzz模式至少有一个(并且不记入分组计数),例如:.com又或者.edu.cn
然后,关注以上表达式首末的语法,(<)? 表示左尖括号没有或者仅有一个,并且由于是第一个分组,所以分组的序号为1;而末尾的语法 (?(1)>) 是 (?(id) yes-pattern | no-pattern) 的省略写法,省略了no-pattern部分,以第一个分组的匹配结果为条件,若找到左尖括号,则相应整体的正则表达式最后会添加上右尖括号从而形成配对;否则无需指定多余的匹配模式;如此一来便可实现对以下两种形式的邮箱地址进行匹配 user@host.com 或者 <user@host.com>

测试源码

更多详细的测试案例参见下方测试代码
Python-Study/regex_study.py

参考

No comments:

Post a Comment