python_正则表达式
正则表达式
正则表达式(称为RE,或正则,或正则表达式模式)本质上是嵌入在Python中的一种微小的、高度专业化的编程语言,可通过 re 模块获得。 使用这种小语言,你可以为要匹配的可能字符串集指定规则;此集可能包含英语句子,电子邮件地址,TeX命令或你喜欢的任何内容。 然后,您可以询问诸如“此字符串是否与模式匹配?”或“此字符串中的模式是否匹配?”等问题。 你还可以使用正则修改字符串或以各种方式将其拆分。
正则表达式模式被编译成一系列字节码,然后由用 C 编写的匹配引擎执行。对于高级用途,可能需要特别注意引擎如何执行给定的正则,并将正则写入以某种方式生成运行速度更快的字节码。 本文档未涉及优化,因为它要求你充分了解匹配引擎的内部结构。
正则表达式语言相对较小且受限制,因此并非所有可能的字符串处理任务都可以使用正则表达式完成。 还有一些任务 可以 用正则表达式完成,但表达式变得非常复杂。 在这些情况下,你最好编写 Python 代码来进行处理;虽然 Python 代码比精心设计的正则表达式慢,但它也可能更容易理解。
正则表达式的语法
正则表达式(或 RE)指定了一组与之匹配的字符串;模块内的函数可以检查某个字符串是否与给定的正则表达式匹配
python中的正则表达式有内置的模块re. 只要导入就能使用。(import re
)
re模块的方法
有了准备知识,我们就可以在Python中使用正则表达式了。Python提供re模块,包含所有正则表达式的功能。由于Python的字符串本身也用\转义,所以要特别注意。 因此强烈建议使用Python的r前缀(raw模式),就不用考虑转义的问题了
方法 / 属性 | 目的 |
---|---|
match() | 确定正则是否从字符串的开头匹配。 |
search() | 扫描字符串,查找此正则匹配的任何位置。 |
findall() | 找到正则匹配的所有子字符串,并将它们作为列表返回。 |
finditer() | 找到正则匹配的所有子字符串,并将它们返回为一个 iterator。 |
sub() | 用于替换字符串中的匹配项 |
split() | 将字符串拆分成列表 |
match()方法
- 判断是否匹配,如果匹配成功,返回一个Match对象,否则返回None。
- 从头开始匹配
1 | import re |
1 | <re.Match object; span=(0, 9), match='010-12345'> |
查看匹配结果
方法 / 属性 | 目的 |
---|---|
group() | 返回正则匹配的字符串 |
start() | 返回匹配的开始位置 |
end() | 返回匹配的结束位置 |
span() | 返回包含匹配 (start, end) 位置的元组 |
- group() 返回正则匹配的子字符串。
- start() 和 end() 返回匹配的起始和结束索引。
- span() 在单个元组中返回开始和结束索引。
- 由于 match() 方法只检查正则是否在字符串的开头匹配,所以 start() 将始终为零。
如果正则表达式中定义了组,就可以在Match对象上用group()方法提取出子串来。
注意到group(0)永远是原始字符串,group(1)、group(2)……表示第1、2、……个子串。
但是,模式的 search() 方法会扫描字符串,因此在这种情况下匹配可能不会从零开始。:
exp
1 | result=re.match(r'\d{3}-\d{3,8}', '010-12345678') |
1 | <re.Match object; span=(0, 12), match='010-12345678'> |
exp
1 | result=re.match(r'(\d{3})-\d{3,8}', '010-1234567890') |
1 | <re.Match object; span=(0, 12), match='010-12345678'> |
serch()方法
- 在要查找的字符串中从左到右开始查找,找到1个后就返回匹配对象,否则None
exp
1 | result=re.search (r'(\d{3})-(\d{3,8})', '087010-123456789013579-1234678902468') |
1 | <re.Match object; span=(3, 15), match='010-12345678'> |
findall()方法
- 在查找范围内找出所有符合条件的匹配对象
- 返回一个列表
exp
1 | result=re.findall (r'(\d{3})-(\d{3,8})', '087010-123456789013579-1234678902468') |
1 | [('010', '12345678'), ('579', '12346789')] |
finditer() 方法
- 将一个 匹配对象 的序列返回为一个 iterator
exp
1 | result = re.finditer(r'(\d{3})-(\d{3,8})', |
1 | <callable_iterator at 0x67c3238> |
exp
[<re.Match object; span=(3, 15), match='010-12345678'>,
<re.Match object; span=(19, 31), match='579-12346789'>]
1 |
|
1 | <callable_iterator at 0x66ae9b8> |
sub()方法
- 用于替换字符串中的匹配项
exp
1 | # 将‘-’ 替换成空格‘***’ |
1 | '087010***123456789013579***1234678902468' |
exp
1 | # 将大于4的数字 替换成空格‘***’ |
1 | '0**010-1234*****013***-1234****024**' |
split方法
- 能够按照所能匹配的字串将字符串进行切分,返回切分后的字符串列表
re.split(pattern, string, maxsplit=0, flags=0)
- pattern:匹配的字符串
- string:需要切分的字符串
- maxsplit:分隔次数,默认为0(即不限次数)
- flags:标志位,用于控制正则表达式的匹配方式,比如:是否区分大小写
exp
1 | str1 = 'ab cde f gHi' |
1 | ['ab', 'cde', 'f', '', 'gHi'] |
exp
1 | str1 = 'ab cde f gHi' |
1 | ['ab', 'cde', 'f gHi'] |
元字符
. ^ $ * + ? { } [ ] \ | ( )
符号 | 意义 |
---|---|
. |
半角句号,匹配任意单个字符,除了换行符。 |
[ ] | 字符种类。匹配方括号内的任意字符 |
[^] |
否定的字符种类。匹配除了方括号内的任意字符 |
* |
匹配 >= 0 个重复的 在 * 号之前的字符 |
+ |
匹配 >= 1 个重复的 在 + 号之前的字符 |
? |
匹配 0 ~1 个重复的 在 ? 号之前的字符 |
{n} |
匹配 = n 个 {} 号之前的字符或字符集 |
{n,} |
匹配 >=n 个 {} 号之前的字符或字符集 |
{n,m} |
匹配 >=n ~ <=m 个 {} 号之前的字符或字符集 |
(abc) |
字符集。匹配与 abc 相等的字符串 |
| |
或 运算符。匹配符号前或后的字符 |
^ |
从首位开始匹配 |
$ |
从末尾开始匹配 |
\ |
转义字符。用于匹配一些保留的字符 如:[] () { } . * + ? ^ $ \ | |
组合
(...)
(组合),匹配括号内的任意正则表达式,并标识出组合的开始和结尾。匹配完成后,组合的内容可以被获取,并可以在之后用 \number 转义序列进行再次匹配,之后进行详细说明。要匹配字符 ‘(‘ 或者 ‘)’, 用 ( 或 ), 或者把它们包含在字符集合里: [(], [)].
(?…)
这是个扩展标记法 (一个 ‘?’ 跟随 ‘(‘ 并无含义)。 ‘?’ 后面的第一个字符决定了这个构建采用什么样的语法。这种扩展通常并不创建新的组合; (?P <name>
…) 是唯一的例外。 以下是目前支持的扩展。
(?aiLmsux)
( ‘a’, ‘i’, ‘L’, ‘m’, ‘s’, ‘u’, ‘x’ 中的一个或多个) 这个组合匹配一个空字符串;这些字符对正则表达式设置以下标记 re.A (只匹配ASCII字符), re.I (忽略大小写), re.L (语言依赖), re.M (多行模式), re.S (点dot匹配全部字符), re.U (Unicode匹配), and re.X (冗长模式)。 (这些标记在 模块内容 中描述) 如果你想将这些标记包含在正则表达式中,这个方法就很有用,免去了在 re.compile() 中传递 flag 参数。标记应该在表达式字符串首位表示。
(?:…)
正则括号的非捕获版本。 匹配在括号内的任何正则表达式,但该分组所匹配的子字符串 不能 在执行匹配后被获取或是之后在模式中被引用。
(?aiLmsux-imsx:…)
(‘a’, ‘i’, ‘L’, ‘m’, ‘s’, ‘u’, ‘x’ 中的0或者多个, 之后可选跟随 ‘-‘ 在后面跟随 ‘i’ , ‘m’ , ‘s’ , ‘x’ 中的一到多个 .) 这些字符为表达式的其中一部分 设置 或者 去除 相应标记 re.A (只匹配ASCII), re.I (忽略大小写), re.L (语言依赖), re.M (多行), re.S (点匹配所有字符), re.U (Unicode匹配), and re.X (冗长模式)。(标记描述在 模块内容 .)
‘a’, ‘L’ and ‘u’ 作为内联标记是相互排斥的, 所以它们不能结合在一起,或者跟随 ‘-‘ 。 当他们中的某个出现在内联组中,它就覆盖了括号组内的匹配模式。在Unicode样式中, (?a:…) 切换为 只匹配ASCII, (?u:…) 切换为Unicode匹配 (默认). 在byte样式中 (?L:…) 切换为语言依赖模式, (?a:…) 切换为 只匹配ASCII (默认)。这种方式只覆盖组合内匹配,括号外的匹配模式不受影响。
(?P<name>…)
(命名组合)类似正则组合,但是匹配到的子串组在外部是通过定义的 name 来获取的。组合名必须是有效的Python标识符,并且每个组合名只能用一个正则表达式定义,只能定义一次。一个符号组合同样是一个数字组合,就像这个组合没有被命名一样。
命名组合可以在三种上下文中引用。如果样式是 (?P
<quote>
[‘“]).*?(?P=quote) (也就是说,匹配单引号或者双引号括起来的字符串):
引用组合 “quote” 的上下文 | 引用方法 |
---|---|
在正则式自身内 | (?P=quote) (如示)\1 |
处理匹配对象m | m.group('quote')``m.end('quote') (等) |
传递到 re.sub() 里的 repl 参数中 |
\g<quote>``\g<1>``\1 |
(?P=name)
反向引用一个命名组合;它匹配前面那个叫 name 的命名组中匹配到的串同样的字串。
(?#…)
(?#…)
注释;里面的内容会被忽略。
(?=…)
匹配 … 的内容,但是并不消费样式的内容。这个叫做 lookahead assertion。比如, Isaac (?=Asimov) 匹配 ‘Isaac ‘ 只有在后面是 ‘Asimov’ 的时候。
(?!…)
匹配 … 不符合的情况。这个叫 negative lookahead assertion (前视取反)。比如说, Isaac (?!Asimov) 只有后面 不 是 ‘Asimov’ 的时候才匹配 ‘Isaac ‘ 。
(?<=…)
匹配字符串的当前位置,它的前面匹配 … 的内容到当前位置。这叫 positive lookbehind assertion (正向后视断定)。 (?<=abc)def 会在 ‘abcdef’ 中找到一个匹配,因为后视会往后看3个字符并检查是否包含匹配的样式。包含的匹配样式必须是定长的,意思就是 abc 或 a|b 是允许的,但是 a* 和 a{3,4} 不可以。注意以 positive lookbehind assertions 开始的样式,如 (?<=abc)def ,并不是从 a 开始搜索,而是从 d 往回看的。你可能更加愿意使用 search() 函数,而不是 match() 函数:
(?<!…)
匹配当前位置之前不是 … 的样式。这个叫 negative lookbehind assertion (后视断定取非)。类似正向后视断定,包含的样式匹配必须是定长的。由 negative lookbehind assertion 开始的样式可以从字符串搜索开始的位置进行匹配.
(?(id/name)yes-pattern|no-pattern)
如果给定的 id 或 name 存在,将会尝试匹配 yes-pattern ,否则就尝试匹配 no-pattern,no-pattern 可选,也可以被忽略。
比如,()?(\w+@\w+(?:.\w+)+)(?(1)?(%5Cw+@%5Cw+(?:%5C.%5Cw+)+)(?(1))|$)
是一个email样式匹配,将匹配 ‘user@host.com‘ 或 ‘user@host.com‘ ,但不会匹配 ‘<user@host.com‘ ,也不会匹配 ‘user@host.com>’。
\
和字母的特殊序列
\number
匹配数字代表的组合。每个括号是一个组合,组合从1开始编号。比如
(.+) \1
匹配 ‘the the’ 或者 ‘55 55’, 但不会匹配 ‘thethe’ (注意组合后面的空格)。这个特殊序列只能用于匹配前面99个组合。如果 number 的第一个数位是0, 或者 number 是三个八进制数,它将不会被看作是一个组合,而是八进制的数字值。在 ‘[‘ 和 ‘]’ 字符集合内,任何数字转义都被看作是字符。
\A
只匹配字符串开始。
\b
和 \B
\b
匹配空字符串,但只在单词开始或结尾的位置。一个单词被定义为一个单词字符的序列。注意,通常 \b 定义为 \w 和 \W 字符之间,或者 \w 和字符串开始/结尾的边界, 意思就是 r’\bfoo\b’ 匹配 ‘foo’, ‘foo.’, ‘(foo)’, ‘bar foo baz’ 但不匹配 ‘foobar’ 或者 ‘foo3’。
\B
匹配空字符串,但不能在词的开头或者结尾。意思就是 r’py\B’ 匹配 ‘python’, ‘py3’, ‘py2’, 但不匹配 ‘py’, ‘py.’, 或者 ‘py!’. \B 是 \b 的取非,所以Unicode样式的词语是由Unicode字母,数字或下划线构成的,虽然可以用 ASCII 标志来改变。如果使用了 LOCALE 标志,则词的边界由当前语言区域设置。
\d
和 \D
\d
对于 Unicode (str) 样式:
匹配任何Unicode十进制数(就是在Unicode字符目录[Nd]里的字符)。这包括了 [0-9] ,和很多其他的数字字符。如果设置了 ASCII 标志,就只匹配 [0-9] 。对于8位(bytes)样式:匹配任何十进制数,就是 [0-9]。
\D
匹配任何非十进制数字的字符。就是 \d 取非。 如果设置了 ASCII 标志,就相当于 [^0-9] 。
\s
和 \S
\s
对于 Unicode (str) 样式:匹配任何Unicode空白字符(包括 [ \t\n\r\f\v] ,还有很多其他字符,比如不同语言排版规则约定的不换行空格)。如果 ASCII 被设置,就只匹配 [ \t\n\r\f\v] 。对于8位(bytes)样式:匹配ASCII中的空白字符,就是 [ \t\n\r\f\v] 。
\S
匹配任何非空白字符。就是 \s 取非。如果设置了 ASCII 标志,就相当于 [^ \t\n\r\f\v] 。
\w
和 \W
\w
对于 Unicode (str) 样式:匹配Unicode词语的字符,包含了可以构成词语的绝大部分字符,也包括数字和下划线。如果设置了 ASCII 标志,就只匹配[a-zA-Z0-9_]
。对于8位(bytes)样式:匹配ASCII字符中的数字和字母和下划线,就是[a-zA-Z0-9_]
。如果设置了 LOCALE 标记,就匹配当前语言区域的数字和字母和下划线。
\W
匹配非单词字符的字符。这与\w
正相反。如果使用了 ASCII 旗标,这就等价于[^a-zA-Z0-9_]
。如果使用了 LOCALE 旗标,则会匹配当前区域中既非字母数字也非下划线的字符。
\Z
只匹配字符串尾。
常用表达式
校验字符
匹配内容 | 表达式 |
---|---|
汉字 | ^[\u4e00-\u9fa5]{0,}$ |
英文和数字 | ^[A-Za-z0-9]+$ ``或 ^[A-Za-z0-9]{4,40}$ |
长度为3-20的所有字符 | ^.{3,20}$ |
由26个英文字母组成的字符串 | ^[A-Za-z]+$ |
由26个大写英文字母组成的字符串 | ^[A-Z]+$ |
由26个小写英文字母组成的字符串 | ^[a-z]+$ |
由数字和26个英文字母组成的字符串 | ^[A-Za-z0-9]+$ |
由数字、26个英文字母或者下划线组成的字符串 | ^\w+$ 或 ^\w{3,20}$ |
中文、英文、数字包括下划线 | ^[\u4E00-\u9FA5A-Za-z0-9_]+$ |
中文、英文、数字但不包括下划线等符号 | ^[\u4E00-\u9FA5A-Za-z0-9]+$ ``或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$ |
可以输入含有^%&’,;=?$"等字符 | [^%&',;=?$\x22]+ 12 |
禁止输入含有~的字符 | [^~\x22]+ |
全角符号 | [\uFF00-\uFFFF] |
半角符号 | [\u0000-\u00FF] |
校验数字
匹配内容 | 表达式 |
---|---|
数字 | ^[0-9]*$ |
n位的数字 | ^\d{n}$ |
至少n位的数字 | ^\d{n,}$ |
m-n位的数字 | ^\d{m,n}$ |
零和非零开头的数字 | ^(0|[1-9][0-9]*)$ |
非零开头的最多带两位小数的数字 | ^([1-9][0-9]*)+(.[0-9]{1,2})?$ |
带1-2位小数的正数或负数 | ^(\-)?\d+(\.\d{1,2})?$ |
正数、负数、和小数 | ^(\-|\+)?\d+(\.\d+)?$ |
有两位小数的正实数 | ^[0-9]+(.[0-9]{2})?$ |
有1~3位小数的正实数 | ^[0-9]+(.[0-9]{1,3})?$ |
非零的正整数 | ^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$ |
非零的负整数 | ^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$ |
非负整数 | ^\d+$ 或 ^[1-9]\d*|0$ |
非正整数 | ^-[1-9]\d*|0$ <或 ^((-\d+)|(0+))$ |
非负浮点数 | ^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ |
非正浮点数 | ^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ |
正浮点数 | ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$ |
负浮点数 | ^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$ |
浮点数 | ^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$ |
特殊匹配
匹配内容 | 表达式 |
---|---|
Email地址 | ^\w+([-+]\w+)*@\w+([-]\w+)*\\w+([-]\w+)*$ |
域名 | [a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/? |
InternetURL | [a-zA-z]+://[^\s]* 或 ^http://([\w-]+\)+[\w-]+(/[\w-/?%&=]*)?$ |
手机号码 | `^(13[0-9] |
电话号码 | ^(\(\d{3,4}-)|\d{34}-)?\d{7,8}$ |
国内电话号码(0511-4405222、021-87888822) | `\d{3}-\d{8} |
身份证号(15位、18位数字) | ^\d{15}|\d{18}$ |
短身份证号码(数字、字母x结尾) | `^([0-9]){7,18}(x |
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线) | ^[a-zA-Z][a-zA-Z0-9_]{4,15}$ |
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线) | ^[a-zA-Z]\w{5,17}$ |
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间) | ^(?=*\d)(?=*[a-z])(?=*[A-Z]){8,10}$ |
日期格式 | ^\d{4}-\d{1,2}-\d{1,2} |
一年的12个月(01~09和1~12) | `r’^(0?[1-9] |
一个月的31天(01~09和1~31) | `r’^((0?[1-9]) |
xml文件 | `r’^([a-zA-Z]+-?)+[a-zA-Z0-9]+[x |
1到3个数字,后面跟个逗号+3个数字,逗号成为可选,而不是必须 | `r’^([0-9]+ |
中文字符的正则表达式 | r'[\u4e00-\u9fa5]' |
双字节字符 | [^\x00-\xff] (可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)) |
空白行的正则表达式 | r '\n\s*\r' (可以用来删除空白行) |
首尾空白字符的正则表达式 | ^\s*|\s*$ 或 (^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式) |
腾讯QQ号(腾讯QQ号从10000开始) | [1-9][0-9]{4,} |
中国邮政编码 | [1-9]\d{5}(?!\d) |
提取网页图片 | \\<*[img][^\\\\>]*[src]*=*[\\"\\']{0,1}([^\\"\\'\\>]*) |
提取网页颜色代码 | r’^#([A-Fa-f0-9]{6} |
文件扩展名效验 | `r’^([a-zA-Z]:|\)\([^\]+\)[^/:?”<> |