语法表
语法 | 说明 | 表达式实例 | 完整匹配的字符串 |
字符
| |||
一般字符 | 匹配自身 | abc | abc |
. | 匹配任意除换行符“\n”外的字符。 在DOTALL模式中也能匹配换行符。 | a.c | abc |
\ | 转义字符,使后一个字符改变原来的意思。 如果字符串中有字符*需要匹配,可以使用\*或者字符集[*]。 | a\.c a\\c | a.c a\c |
[...] | 字符集(字符类)。对应的位置可以是字符集中任意字符。 字符集中的字符可以逐个列出,或者给出范围,如[abc]或 [a-c]。第一个字符如果是^则表示取反,如[^abc]表示不是 abc的其他字符。 所有的特殊字符在字符集中都失去其原有的特殊含义。在字 符集中如果要使用 ]、-或^,可以在前面加上转义字符(\), 或把 ]、-放在第一个字符,把^放在非第一个字符。 | a[bcd]e | abe ace ade |
预定义字符集(可以写在字符集[...]中)
| |||
\d | 数字:[0-9] | a\dc | a1c |
\D | 非数字:[^\d] | a\Dc | abc |
\s | 空白字符:[<空格>\t\r\n\f\v] | a\sc | a c |
\S | 非空白字符:[^\s] | a\Sc | abc |
\w | 单词字符:[A-Za-z0-9] | a\wc | abc |
\W | 非单词字符:[^\w] | a\Wc | a c |
数量词(用在字符或(...)之后)
| |||
* | 匹配前一个字符0或无限次。 | abc* | ab abccc |
+ | 匹配前一个字符1次或无限次。 | abc+ | abc abccc |
? | 匹配前一个字符0次或1次。 | abc? | ab abc |
{m} | 匹配前一个字符m次。 | ab{2}c | abbc |
{m,n} | 匹配前一个字符m至n次。 m和n可以省略:若省略m,则匹配0至n次;若省略n,则匹 配m至无限次。 | ab{1,2}c | abc abbc |
*?, +?, ?? {m,n}? | 使*, +, ?, {m,n}变成非贪婪模式 | abc{2,4}? | abcc |
边界匹配(不消耗待匹配字符串中的字母)
| |||
^ | 匹配字符串开头。 在多行模式中匹配每一行的开头。 | ^abc | abc |
$ | 匹配字符串末尾。 在多行模式中匹配每一行的末尾。 | abc$ | abc |
\A | 匹配字符串开头(对多行也仅匹配第一行开头)。 | \Aabc | abc |
\Z | 匹配字符串末尾(对多行也仅匹配最后一行末尾)。 | abc\Z | abc |
\b | 匹配\w和\W之间的字符。 | \bfoo\b | foo bar foo bar (foo) foo2 (not matched) |
\B | 匹配\w字符,但是不位于单词的开头或结尾。 | py\B | python (matched) py 3 (not matched) |
逻辑、分组
| |||
| | 代表左右表达式任意匹配一个。 总是先尝试匹配左边的表达式,一旦成功则跳过匹配 右侧的表达式。如果 | 未被包括在 () 中, 则它的范围是整个正则表达式。 | abc|def | abc def |
(...) | 被括起来的表达式将作为分组,从表达式左边开始每遇到一 个分组的左括号 '(' ,编号+1. 另外,分组表达式作为一个整体,可以后接数量词。 表达式中的 | 仅在该组中有效。 | (abc){2} a(123|456)c | abcabc a456c |
(?P<name>...) | 分组,除了原有的编号外再额外指定一个别名(name) | (?P<id>abc){2} | abcabc |
\<number> | 引用编号为<number>的分组匹配到的字符串。 | (\d)abc\1 | 1abc1 5abc5 |
(?P=name) | 引用别名为<name>的分组匹配到的字符串。 | (?P<id>\d)abc(?P=id) | 1abc1 5abc5 |
特殊构造(不作为分组,即不增加分组号)
| |||
(?:...) | (...)的不分组版本 | (?:\d)(\d)abc\1 | 12abc2 (matched) 12abc1 (not matched) |
(?#...) | #后为注释内容,不形成匹配模式 | (?#comment)abc | abc |
(?=...) | 之后的字符串需要匹配表达式中的内容。 不消耗字符串内容。 | abc(?=123) | abc123 (matched) 匹配结果为 abc, 而不是 abc123。 abc12 (not matched) |
(?!...) | 之后的字符串不是表达式中的内容,才匹配。 不消耗字符串内容。 | abc(?!123) | abc123 (not matched) abc12 (matched) 匹配结果为 abc, 而不是 abc12。 |
(?<=...) | 之前的字符串需要匹配表达式中的内容。 不消耗字符串内容。 | (?<=123)abc | 123abc (matched) |
(?<!...) | 之前的字符串不是表达式中的内容,才匹配。 不消耗字符串内容。 | (?!123)abc | 12abc (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
函数负责根据生成正则表达式生成相应的匹配模式,而match
和search
函数则根据匹配模式对目标字符串进行匹配。match
与search
的区别在于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