一:Python 正则表达式
正则表达式(regex)是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
Python1.5版本起通过标准库中的re 模块来支持 Perl 风格的正则表达式。
二:正则表达模式
2.1.符号
表示法 | 描述 | 正则表达式实例 |
literal | 匹配文本字符串的字面值literal | foo |
re1|re2 | 匹配正册表达式re1或者re2 | foo|bar |
. | 匹配任何字符(除了\n之外) | b.b |
^ | 匹配字符串起始部分 | ^Dear |
$ | 匹配字符串终止部分 | /bin/*sh$ |
* | 匹配0次或者多次前面出现的正册表达式 | [A-Za-z0-9]* |
+ | 匹配1次或者多次前面出现的正册表达式 | [a-z]+\.com |
? | 匹配0次或者1次前面出现的正册表达式 | goo? |
{N} | 匹配N次或者多次前面出现的正册表达式 | [0-9]{3} |
{M,N} | 匹配M~N次或者多次前面出现的正册表达式 | [0-9]{5,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 |
2. 2.特殊字符
\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 |
\c | 逐字匹配任何特殊字符c | \,\\,\* |
\A(\z) | 匹配字符串的起始(结束) | \ADear |
2.3.扩展表示法
(?iLmsux) | 在正则表达式中嵌入一个或者多个特殊'标记'参数(或者通过函数、方法) | (?x),(?im) |
(?...) | 表示一个匹配不用保存的分组 | (?:\w+\.)* |
(?P |
像一个仅由name标识而不是数字ID标识的正则分组匹配 | (?P) |
(?P |
在同一字符串中匹配由(?P |
(?P=data) |
(?#...) | 表示注释,所有内容都被忽略 | (?#comment) |
(?=...) | 匹配条件是如果...出现在之后的位置,而不使用输入字符串:称作正向前视断言 | (?=.com) |
(?!...) | 匹配条件是如果...不出现在之后的位置,而不使用输入字符串:称作负向前视断言 | (?!.net) |
(?<=...) | 匹配条件是如果...出现在之前的位置,而不使用输入字符串:称作正向后视断言 | (<=800-) |
(? | 匹配条件是如果...不出现在之前的位置,而不使用输入字符串:称作负向后视断言 | (? |
表示(?(id/name)Y|N) | 如果分组所提供的id或者name(名称)存在,就返回正则表达式的条件匹配Y,如果不存在,就返回N;|N是可选项 | (?(1)y|x) |
2.4.标志修饰符
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
三:正则和python
3.1.re模块
python的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,否则替换所有 |
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 | 点号.通常匹配除了换行符\n之外的所有单个字符,该标记表示点号能够匹配全部字符 |
re.X、re.VERBOSE | 通过反斜线转义,否则所有空格加上#(以及在该行中所有后续问题)都被忽略,除非在一个字符类中或者允许注释并且提高可读性 |
3.2.compile()函数编译正则
compile() 函数将一个字符串编译为字节代码。
语法
以下是 compile() 方法的语法:
compile(source, filename, mode[, flags[, dont_inherit]])
参数
- source -- 字符串或者AST(Abstract Syntax Trees)对象。。
- filename -- 代码文件名称,如果不是从文件读取代码则传递一些可辨认的值。
- mode -- 指定编译代码的种类。可以指定为 exec, eval, single。
- flags -- 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。。
- flags和dont_inherit是用来控制编译源码时的标志
>>>str = "for i in range(0,10): print(i)"
>>> c = compile(str,'','exec') # 编译为字节代码对象
>>> c
at 0x10141e0b0, file "", line 1>
>>> exec(c)
0
1
2
3
4
5
6
7
8
9
>>> str = "3 * 4 + 5"
>>> a = compile(str,'','eval')
>>> eval(a)
17
3.3.group()和groups()
group()要么返回整个匹配的对象,要么返回特定子组。
groups()返回唯一或者全部子组的元组。
#!/usr/bin/python import re line = "Cats are smarter than dogs"; earchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I) print earchObj.group() #Cats are smarter than dogs print earchObj.group(0) #Cats are smarter than dogs print earchObj.group(1) #Cats print earchObj.group(2) #smarter print earchObj.groups() #('Cats', 'smarter')
3.4.match()和search()
re.match()只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;
re.search()匹配整个字符串,直到找到一个匹配。
#!/usr/bin/python import re line = "Cats are smarter than dogs"; matchObj = re.match( r'dogs', line, re.M|re.I) if matchObj: print "match --> matchObj.group() : ", matchObj.group() else: print "No match!!" matchObj = re.search( r'dogs', line, re.M|re.I) if matchObj: print "search --> searchObj.group() : ", matchObj.group() else: print "No match!!"
以上实例运行结果如下:
No match!! search --> searchObj.group() : dogs
3.10.findall()和finditer()
findall()查询字符串中某个正则表达式全部的非重复出现情况。返回值为列表。
#!/usr/bin/python import re line = "Cats are smarter than dogs, how old are you "; print re.findall('ar', line) >>>>['ar', 'ar', 'ar']
finditer()和 findall() 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
#!/usr/bin/python import re line = "Cats are smarter than dogs, how old are you "; for aa in re.finditer('ar', line): print (aa.group() ) >>> ar ar ar
3.11.sub()和subn()
re.sub用于替换字符串中的匹配项。
sub()返回替换后的字符串
subn()返回元组,替换后的字符串和替换的总数。
re.sub(pattern, repl, string, count=0, flags=0)
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
#!/usr/bin/python # -*- coding: UTF-8 -*- import re phone = "2004-959-559 # 这是一个国外电话号码" # 删除字符串中的 Python注释 num = re.sub(r'#.*$', "", phone) numn = re.subn(r'#.*$', "", phone) print "电话号码是: ", num print "电话号码是: ", numn # 删除非数字(-)的字符串 num = re.sub(r'\D', "", phone) numn = re.subn(r'\D', "", phone) print "电话号码是 : ", num print "电话号码是: ", numn >>>>>>>>>>> 电话号码是: 2004-959-559 电话号码是: ('2004-959-559 ', 1) 电话号码是 : 2004959559 电话号码是: ('2004959559', 35)
3.12.splite()
split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
re.split(pattern, string[, maxsplit=0, flags=0])
参数:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
maxsplit | 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
>>>import re >>> re.split('\W+', 'runoob, runoob, runoob.') ['runoob', 'runoob', 'runoob', ''] >>> re.split('(\W+)', ' runoob, runoob, runoob.') ['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', ''] >>> re.split('\W+', ' runoob, runoob, runoob.', 1) ['', 'runoob, runoob, runoob.'] >>> re.split('a*', 'hello world') # 对于一个找不到匹配的字符串而言,split 不会对其作出分割 ['hello world']
3.13.扩展符号
1.(?i)忽略大小写
#!/usr/bin/python # -*- coding: UTF-8 -*- import re line = "Cats are smarter than dogs, how old Are you "; print re.findall('ar', line) print re.findall(r'(?i)ar', line) >>>['ar', 'ar'] >>>['ar', 'ar', 'Ar']
2.(?s).表示/n
#!/usr/bin/python # -*- coding: UTF-8 -*- import re line = '''Cats are smarter than dogs, how old Are you, are you ok? '''; print re.findall(r'ar.+', line) print re.findall(r'(?s)ar.+', line) >>>['are smarter than dogs, ', 'are you ok? '] >>>['are smarter than dogs, \n how old Are you,\n are you ok? ']