正则表达式
特殊符号和字符
元字符:最常见的特殊符号和字符;
表示法 | 描述 | 正则表达式 |
---|---|---|
符号 | ||
literal | 匹配文本字符串的字面值 | foo |
re1|re2 | 匹配正则表达式re1 or re2 | foo | bar |
. | 匹配任何字符(除了\n 之外) | b.b |
^ | 匹配字符串起始部分 | ^Dear |
* | 匹配0次或多次前面出现的正则表达式 | [A-Za-z0-9] |
+ | 匹配1次或者多次前面出现的正则表达式 | [a-z]+\.com |
? | 匹配0次或者1次前面出现的正则表达式 | goo? |
匹配N次前面出现的正则表达式 | [0-9] | |
匹配M~N次前面出现的正则表达式 | [0-9] | |
[...] | 匹配来自字符集的任意单一字符 | [aeiou] |
[.x-y..] | 匹配x~y范围中的任意单一字符 | [0-9],[A-Za-z] |
[^...] | 不匹配此字符集中出现的任何一个字符,包括某一范围的字符(如果在此字符集中出现) | [^aeiou],[^A-Za-z0-9] |
(*|+|?|{})? | 用于匹配上面频繁出现/重复出现符号的非贪婪版本(*,+,?,{}) | .*?[a-z] |
(...) | 匹配封闭的正则表达式,然后另存为子组 | ([0-9]{3})?,f(oo|u)bar |
特殊字符 | ||
\d | 匹配任何十进制数字,与[0-9]一致(\D与\d相反,不匹配任何非数值型的数字) | data\d+.txt |
\w | 匹配任何字母数字字符,有[A-Za-z0-9_]相同(\W与之相反) | [A-Za-z_]\W+ |
\s | 匹配任何空格字符,与[\n\t\r\v\f]相同(\S与之相反) | of\sthe |
\b | 匹配任何单词边界(\B与之相反) | \bThe\b |
|N | 匹配已保存的子组N(参见上面的(...)) | price:\16 |
\A(\Z) | 匹配字符串的起始(结束)(另见上面介绍的^和$) | \ADear |
扩展表示法 | ||
(?iLmsux) | 在正则表达式中嵌入一个或者多个特殊“标记”参数(或者通过函数/方法) | (?x),(? im) |
(?:...) | 表示一个匹配不用保存的分组 | (?:\w+\.)* |
(?P<\name>...) | 像一个仅由name标识而不是数字ID标识的正则分组匹配 | (?P<\data>) |
(?P=\name) | 在同一个字符串中匹配由(?P<name)分组的之前文本 | (?P=data) |
(?#...) | 表示注释,所有内容都被忽略 | (?#comment) |
(?=...) | 匹配条件是如果...出现在之后的位置,而不使用输入字符串;称作正向前视断言 | (?=.com) |
(?!...) | 匹配条件是如果...不出现在之后的位置,而不使用输入字符串;称作负向前视断言 | (?!net) |
(?<!...) | 匹配条件是如果...不出现在之前的位置,而不使用输入字符串;称作负向后视断言 | (?<!192\.168\.) |
(?<=...) | 匹配条件是如果...出现在之前的位置,而不使用输入字符串;称作正向后视断言 | (?<=800-) |
(?(id/name)Y|N) | 如果分组所提供的id或者name(名称)存在,就返回正则表达式的条件匹配Y,如果不存在,就返回N;|N是可选项 | (?(1)y|x) |
使用择一匹配符号匹配多个正则表达式模式
择一匹配,就是(|)这个管道符号,表示一个“从多个模式中选择其中之一”的操作,也叫逻辑或(logical OR)或者并(union),特别要注意的是, 竖线在正则表达式的优先级是最低的, 这就意味着,竖线隔开的部分是一个整体。
点-匹配所有字符
.
表示要匹配除了 换行符
之外的任何 单个
字符。
import re
p = re.compile(r'.色')
for one in p.findall(content):
print(one)
星号-重复匹配任意次
*
表示匹配前面的子表达式任意次,包括0次。
content = '''苹果,是绿色的 橙子,是橙色的 香蕉,是黄色的 乌鸦,是黑色的 猴子,''' import re
p = re.compile(r',.*')
for one in p.findall(content):
print(one)
# 结果:
,是绿色的
,是橙色的
,是黄色的
,是黑色的
,
加号-重复匹配多次
+
表示匹配前面的子表达式一次或多次,不包括0次。
问号-匹配0-1次
?
表示匹配前面的子表达式0次或1次。
花括号-匹配指定次数
花括号表示 前面的字符匹配 指定的次数
。
比如 ,下面的文本
红彤彤,绿油油,黑乎乎,绿油油油油
表达式 油{3}
就表示匹配 连续的 油 字 3次
表达式 油{3,4}
就表示匹配 连续的 油 字 至少3次,至多 4 次
使用闭包操作符实现存在性和频数匹配
在计算机编程语言和编译原理中,该操作称为Kleene闭包。加号+操作符将匹配一次或者多次出现的正则表达式(也叫做正闭包操作符),问好(?)操作符将匹配零次或者一次出现的正则表达式。
扩展表示法
以问好开始(?...),通常用于在判断之前提供标记,实现一个前视(或者后视)匹配,或者条件检查。
贪婪模式和非贪婪模式
‘ * ’,‘ + ’,‘ ? ’ 都是贪婪地,使用他们时,会尽可能多的匹配内容,解决这个问题,就需要使用非贪婪模式,也就是在星号后面加上 ?
,变成这样 <.*?>
source = '<html><head><title>Title</title>'
import re
p = re.compile(r'<.*?>')
print(p.findall(source))
对元字符的转义
反斜杠 \
在正则表达式中有多种用途。是转义元字符本身的方式。比如,我们要在下面的文本中搜索 所有点前面的字符串,也包含点本身,如果我们要搜索的内容本身就包含元字符,就可以使用 反斜杠进行转义。
这里我们就应用使用这样的表达式: .*\.
苹果.是绿色的
橙子.是橙色的
香蕉.是黄色的
import re
p = re.compile(r'.*\.')
for one in p.findall(content):
print(one)
运行结果如下
苹果.
橙子.
香蕉.
方括号-匹配几个字符之一
方括号表示要匹配 指定的几个字符之一 。
比如
[abc]
可以匹配 a, b, 或者 c 里面的任意一个字符。等价于 [a-c]
。
[a-c]
中间的 - 表示一个范围从a 到 c。
如果你想匹配所有的小写字母,可以使用 [a-z]
一些 元字符 在 方括号内 失去了魔法, 变得和普通字符一样了。
比如
[akm.]
匹配 a k m .
里面任意一个字符
这里 .
在括号里面不在表示 匹配任意字符了,而就是表示匹配 .
这个 字符
如果在方括号中使用 ^
, 表示 非
方括号里面的字符集合。
content = 'a1b2c3d4e5'
import re
p = re.compile(r'[^\d]' )
for one in p.findall(content):
print(one)
输出结果为:
a
b
c
d
e
re模块:核心函数和方法
常见的正则表达式属性
函数/方法 | 描 述 |
---|---|
仅仅是re模块函数 | |
compile(pattern,flags=0) | 使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象 |
re模块函数和正则表达式对象的方法 | |
match(pattern,string,flags=0) | 尝试使用带有可选标记的正则表达式的模式来匹配字符串。如果匹配成功,就返回匹配对象;如果失败,就返回None |
search(pattern,string,flags=0) | 使用可选标记搜索字符串中第一次出现的正则表达式模式。如果匹配成功,则返回匹配对象;如果失败,则返回None |
findall(pattern,string,[,flags]) | 查找字符串中所有(非重复)出现的正则表达式模式,并返回一个匹配列表 |
finditer(pattern,string,[,flags]) | 与findall()函数相同,但返回的不是一个列表,而是一个迭代器。对于每一次匹配,迭代器都返回一个匹配对象 |
split(pattern,string,max=0) | 根据正则表达式的模式分隔符,split函数将字符串分割为列表,然后返回成功匹配的列表,分隔最多操作max次(默认分割所有匹配成功的位置) |
re模块函数和正则表达式对象方法 | |
sub(pattern,repl,string,count=0) | 使用repl替换所有正则表达式的模式在字符串中出现的位置,除非定义count,否则就将替换所有出现的位置(另见subn()函数,该函数返回替换操作的数目) |
purge() | 清楚隐式编译的正则表达式模式 |
常用的匹配对象方法 | |
group(num=0) | 返回整个函数对象,或者编号为num的特定子组 |
groups(default=None) | 返回一个包含所有匹配子组的元组(如果没有匹配成功,则返回一个空元组) |
groupdict(default=None) | 返回一个包含所有匹配的命名子组的字典,所有的子组名称作为字典的健(如果没有成功匹配,则返回一个空字典) |
常用的模块属性(用于大多数正则表达式函数的标记) | |
re.I/re.IGNORECASE | 不区分大小写的匹配 |
re.L/re.LOCALE | 根据所使用的本地语言环境通过\w,\W,\b,\B,\s,\S实现匹配 |
re.M/re.MULTILINE | 匹配多行 |
re.S/re.DOTALL | 该标记表示“.”(点号)能够匹配全部字符 |
re.X/re.VERBOSE | 通过反斜杠转义,否则所以有空格加上#(以及在该行中所有后续文字)都被忽略,除非在一个字符类中或者允许注释并且提高可读性 |
使用compile()函数编译正则表达式
match()函数
从文本中的起始位开始匹配
search()函数
可以从文本中的任何位置开始匹配
findall()和finditer()查找每一次出现的位置
findall()查询字符串中某个正则表达式模式全部的非重复出现情况,与match()与search()不同之处在于,findall()总是返回一个列表。如果该函数没有找到匹配的部分,就返回一个空列表,但如果匹配成功,列表将包含所有成功的匹配部分(从左向右按出现顺序排列)。
>>> m = re.search('^The','The end.')
>>> re.findall('cat','cat')
['cat']
>>> re.findall('car','scary')
['car']
>>> re.findall('car','carry the barcardi to the car')
['car', 'car', 'car']
finditer()函数是在Python2.2版本中添加回来的,这是一个与findall()函数类似但是更节省内存的变体。两者之间以及和其他变体函数之间的差异(很明显不同于返回的是一个迭代器还是列表)在于,和返回的匹配字符串相比,finditer()在匹配对象中迭代。
>>> import re
>>> s = 'This and that'
>>> re.finditer(r'(th\w+) and (th\w+)',s,re.I).next().groups()
('This','that')
使用sub()和subn()搜索与替换
sub()和subn()用于实现搜索和替换功能。都是将某字符串中所有匹配正则表达式的部分进行某种形式的替换。用来替换的部分通常是一个字符串,但它也可能是一个函数,该函数返回一个用来替换的字符串。sub()和subn()一样,但后者还返回一个表示替换的总数,替换后的字符串和表示替换总数的数字一起作为一个拥有两个元素的元组返回。
>>> re.sub('X','Mr.Smith','attn: X\n\nDear X,\n')
'attn: Mr.Smith\n\nDear Mr.Smith,\n'
>>> re.subn('X','Mr.Smith','attn: X\n\nDear X,\n')
('attn: Mr.Smith\n\nDear Mr.Smith,\n', 2)
限定模式上使用split()分隔字符串
re模块和正则表达式的对象方法split()对于相对应字符串的工作方式是类似的,但是与分隔一个固定字符串相比,它们基于正则表达式的模式分隔字符串,为字符串分隔功能添加一些额外的威力。简单例子
>>> re.split(':','str1:str2:str3')
['str1', 'str2', 'str3']
# 这是一个正则表达式例子
import re
DATA = {
'Mountaain View, CA 94040',
'Sunnyvale,CA',
'Los Altos, 94023',
'Cuperino 95014',
'Palo Alto CA',
}
for datum in DATA:
print (re.split(', |(?= (?:\d{5}|[A-Z]{2}))',datum))
# 结果
['Cuperino', ' 95014']
['Sunnyvale,CA']
['Los Altos', '94023']
['Mountaain View', 'CA', ' 94040']
['Palo Alto', ' CA']
扩展符号
通过使用(?iLmsux)系列选项,用户可以直接在正则表达式里面指定一个或者多个标记,而不是通过compile()或者其他re模块函数。下面为一些使用re.I/IGNORECASE的示例,最后一个示例在re.M/MULTILINE实现多行混合:
>>> re.findall(r'(?i)yes','yes?Yes. YES!!')
['yes', 'Yes', 'YES']
>>> re.findall(r'(?im)(^th[\w]+)',"""
... This line is the first,
... another line,
... that line,it's the best
... """)
['This', 'that']