http://blog.csdn.net/pipisorry/article/details/45476817
Python除了 str 对象自带的一些方法外,re文字处理能力也很强大。
Python中转义字符
正则表达式使用反斜杠" \ "来代表特殊形式或用作转义字符,这里跟Python的语法冲突,因此,Python用" \\\\ "表示正则表达式中的" \ ",因为正则表达式中如果要匹配" \ ",需要用\来转义,变成" \\ ",而Python语法中又需要对字符串中每一个\进行转义,所以就变成了" \\\\ "。
上面的写法是不是觉得很麻烦,为了使正则表达式具有更好的可读性,Python特别设计了原始字符串(raw string),需要提醒你的是,在写文件路径的时候就不要使用raw string了,这里存在陷阱。raw string就是用’r’作为字符串的前缀,如 r”\n”:表示两个字符”\”和”n”,而不是换行符了。Python中写正则表达式时推荐使用这种形式。
正则表达式元字符说明
. 匹配除换行符以外的任意字符
^ 匹配字符串的开始
$ 匹配字符串的结束
[] 用来匹配一个指定的字符类别
? 对于前一个字符字符重复0次到1次
*对于前一个字符重复0次到无穷次
{} 对于前一个字符重复m次
{m,n} 对前一个字符重复为m到n次
\d 匹配数字,相当于[0-9]
\D 匹配任何非数字字符,相当于[^0-9]
\s 匹配任意的空白符,相当于[ fv]
\S 匹配任何非空白字符,相当于[^ fv]
\w 匹配任何字母数字字符,相当于[a-zA-Z0-9_]
\W 匹配任何非字母数字字符,相当于[^a-zA-Z0-9_]
\b 匹配单词的开始或结束
通配符和正则表达式 linux\python\django\notepad++
基本规则
‘[‘ ‘]’ 字符集合设定符
首先说明一下字符集合设定的方法。由一对方括号括起来的字符,表明一个字符集合,能够匹配包含在其中的任意一个字符。比如 [abc123],表明字符’a’ ‘b’ ‘c’ ‘1’ ‘2’ ‘3’都符合它的要求。可以被匹配。
在’[‘ ‘]’中还可以通过 ’-‘ 减号来指定一个字符集合的范围,比如可以用[a-zA-Z]来指定所以英文字母的大小写,因为英文字母是按照从小到大的顺序来排的。你不可以把大小的顺序颠倒了,比如写成[z-a]就不对了。
如果在’[‘ ‘]’里面的开头写一个 ‘^’ 号,则表示取非,即在括号里的字符都不匹配。如[^a-zA-Z]表明不匹配所有英文字母。但是如果 ‘^’不在开头,则它就不再是表示取非,而表示其本身,如[a-z^A-Z]表明匹配所有的英文字母和字符’^’。
‘|’ 或规则
将两个规则并列起来,以‘|’连接,表示只要满足其中之一就可以匹配。比如
[a-zA-Z]|[0-9] 表示满足数字或字母就可以匹配,这个规则等价于 [a-zA-Z0-9]
注意:关于’|’要注意两点:
第一, 它在’[‘ ‘]’之中不再表示或,而表示他本身的字符。如果要在’[‘ ‘]’外面表示一个’|’字符,必须用反斜杠引导,即 ’/|’ ;
第二, 它的有效范围是它两边的整条规则,比如‘dog|cat’匹配的是‘dog’和’cat’,而不是’g’和’c’。如果想限定它的有效范围,必需使用一个无捕获组 ‘(?: )’包起来。比如要匹配 ‘I have a dog’或’I have a cat’,需要写成r’I have a (?:dog|cat)’ ,而不能写成 r’I have a dog|cat’
例
s = ‘I have a dog , I have a cat’
re.findall( r’I have a (?:dog|cat)’ , s )
[‘I have a dog’, ‘I have a cat’] #正如我们所要的
下面再看看不用无捕获组会是什么后果:
re.findall( r’I have a dog|cat’ , s )
[‘I have a dog’, ‘cat’] #它将’I have a dog’ 和’cat’当成两个规则了
至于无捕获组的使用,后面将仔细说明。这里先跳过。
‘.’ 匹配所有字符
匹配除换行符’\n’外的所有字符。如果使用了’S’选项,匹配包括’\n’的所有字符。
例:
s=’123 \n456 \n789’
findall(r‘.+’,s)
[‘123’, ‘456’, ‘789’]
re.findall(r‘.+’ , s , re.S)
[‘123\n456\n789’]
‘^’和’$’ 匹配字符串开头和结尾
注意’^’不能在‘[ ]’中,否则含意就发生变化,具体请看上面的’[‘ ‘]’说明。 在多行模式下,它们可以匹配每一行的行首和行尾。具体请看后面compile函数说明的’M’选项部分
‘\d’ 匹配数字
这是一个以’\’开头的转义字符,’\d’表示匹配一个数字,即等价于[0-9]
‘\D’ 匹配非数字
这个是上面的反集,即匹配一个非数字的字符,等价于[^0-9]。注意它们的大小写。下面我们还将看到Python的正则规则中很多转义字符的大小写形式,代表互补的关系。这样很好记。
‘\w’ 匹配字母和数字
匹配所有的英文字母和数字,即等价于[a-zA-Z0-9]。
‘\W’ 匹配非英文字母和数字
即’\w’的补集,等价于[^a-zA-Z0-9]。
‘\s’ 匹配间隔符
即匹配空格符、制表符、回车符等表示分隔意义的字符,它等价于[ \t\r\n\f\v]。(注意最前面有个空格)
‘\S’ 匹配非间隔符
即间隔符的补集,等价于[^ \t\r\n\f\v]
‘\A’ 匹配字符串开头
匹配字符串的开头。它和’^’的区别是,’\A’只匹配整个字符串的开头,即使在’M’模式下,它也不会匹配其它行的行首。
‘\Z’ 匹配字符串结尾
匹配字符串的结尾。它和’$’的区别是,’\Z’只匹配整个字符串的结尾,即使在’M’模式下,它也不会匹配其它各行的行尾。
例:
s= ‘12 34\n56 78\n90’
re.findall( r’^\d+’ , s , re.M ) #匹配位于行首的数字
[‘12’, ‘56’, ‘90’]
re.findall( r’\A\d+’, s , re.M ) #匹配位于字符串开头的数字
[‘12’]
re.findall( r’\d+$’ , s , re.M ) #匹配位于行尾的数字
[‘34’, ‘78’, ‘90’]
re.findall( r’\d+\Z’ , s , re.M ) #匹配位于字符串尾的数字
[‘90’]
‘\b’ 匹配单词边界
它匹配一个单词的边界,比如空格等,不过它是一个‘0’长度字符,它匹配完的字符串不会包括那个分界的字符。而如果用’\s’来匹配的话,则匹配出的字符串中会包含那个分界符。
例:
s = ‘abc abcde bc bcd’
re.findall( r’\bbc\b’ , s ) #匹配一个单独的单词 ‘bc’ ,而当它是其它单词的一部分的时候不匹配
[‘bc’] #只找到了那个单独的’bc’
re.findall( r’\sbc\s’ , s ) #匹配一个单独的单词 ‘bc’
[’ bc ‘] #只找到那个单独的’bc’,不过注意前后有两个空格,可能有点看不清楚
‘\B’ 匹配非边界
和’\b’相反,它只匹配非边界的字符。它同样是个0长度字符。
接上例:
re.findall( r’\Bbc\w+’ , s ) #匹配包含’bc’但不以’bc’为开头的单词
[‘bcde’] #成功匹配了’abcde’中的’bcde’,而没有匹配’bcd’
‘(?:)’ 无捕获组
当你要将一部分规则作为一个整体对它进行某些操作,比如指定其重复次数时,你需要将这部分规则用’(?:’ ‘)’把它包围起来,而不能仅仅只用一对括号,那样将得到绝对出人意料的结果。
例:匹配字符串中重复的’ab’
s=’ababab abbabb aabaab’
re.findall( r’\b(?:ab)+\b’ , s )
[‘ababab’]
如果仅使用一对括号,看看会是什么结果:
re.findall( r’b(ab)+\b’ , s )
[‘ab’]
这是因为如果只使用一对括号,那么这就成为了一个组(group)。
‘(?# )’ 注释
Python允许你在正则表达式中写入注释,在’(?#’ ‘)’之间的内容将被忽略。
(?iLmsux) 编译选项指定
Python的正则式可以指定一些选项,这个选项可以写在findall或compile的参数中,也可以写在正则式里,成为正则式的一部分。这在某些情况下会便利一些。具体的选项含义请看后面的compile函数的说明。
此处编译选项’i’ 等价于IGNORECASE ,L 等价于 LOCAL ,m 等价于 MULTILINE ,s 等价于 DOTALL ,u 等价于 UNICODE , x 等价于 VERBOSE 。
请注意它们的大小写。在使用时可以只指定一部分,比如只指定忽略大小写,可写为 ‘(?i)’,要同时忽略大小写并使用多行模式,可以写为 ‘(?im)’。
另外要注意选项的有效范围是整条规则,即写在规则的任何地方,选项都会对全部整条正则式有效。
前向界定与后向界定
有时候需要匹配一个跟在特定内容后面的或者在特定内容前面的字符串,Python提供一个简便的前向界定和后向界定功能,或者叫前导指定和跟从指定功能。它们是:
‘(?<=…)’ 前向界定
括号中’…’代表你希望匹配的字符串的前面应该出现的字符串。
‘(?=…)’ 后向界定
括号中的’…’代表你希望匹配的字符串后面应该出现的字符串。
例: 你希望找出c语言的注释中的内容,它们是包含在’/’和’/’之间,不过你并不希望匹配的结果把’/’和’/’也包括进来,那么你可以这样用:
s=r’/* comment 1 / code / comment 2 */’
re.findall( r’(?<=/*).+?(?=*/)’ , s )
[’ comment 1 ‘, ’ comment 2 ‘]
注意这里我们仍然使用了最小匹配,以避免把整个字符串给匹配进去了。
要注意的是,前向界定括号中的表达式必须是常值,也即你不可以在前向界定的括号里写正则式。比如你如果在下面的字符串中想找到被字母夹在中间的数字,你不可以用前向界定:
例:
s = ‘aaa111aaa , bbb222 , 333ccc ‘
re.findall( r’(?<=[a-z]+)\d+(?=[a-z]+)’ , s ) # 错误的用法
它会给出一个错误信息:
error: look-behind requires fixed-width pattern
不过如果你只要找出后面接着有字母的数字,你可以在后向界定写正则式:
re.findall( r’\d+(?=[a-z]+)’, s )
[‘111’, ‘333’]
如果你一定要匹配包夹在字母中间的数字,你可以使用组(group)的方式
re.findall (r’[a-z]+(\d+)[a-z]+’ , s )
[‘111’]
组的使用将在后面详细讲解。
前向非界定和后向非界定
‘(?< !…)’前向非界定(<和!中间是没有空格的,makedown编辑器会将< !当成注释,不显示==!给醉了。。。)
只有当你希望的字符串前面不是’…’的内容时才匹配
‘(?!…)’后向非界定
只有当你希望的字符串后面不跟着’…’内容时才匹配。
接上例,希望匹配后面不跟着字母的数字
re.findall( r’\d+(?!\w+)’ , s )
[‘222’]
注意这里我们使用了\w而不是像上面那样用[a-z],因为如果这样写的话,结果会是:
re.findall( r’\d+(?![a-z]+)’ , s )
[‘11’, ‘222’, ‘33’]
这和我们期望的似乎有点不一样。它的原因,是因为’111’和’222’中的前两个数字也是满足这个要求的。因此可看出,正则式的使用还是要相当小心的,因为我开始就是这样写的,看到结果后才明白过来。不过Python试验起来很方便,这也是脚本语言的一大优点,可以一步一步的试验,快速得到结果,而不用经过烦琐的编译、链接过程。也因此学习Python就要多试,跌跌撞撞的走过来,虽然曲折,却也很有乐趣。
组的基本知识
上面我们已经看过了Python的正则式的很多基本用法。不过如果仅仅是上面那些规则的话,还是有很多情况下会非常麻烦,比如上面在讲前向界定和后向界定时,取夹在字母中间的数字的例子。用前面讲过的规则都很难达到目的,但是用了组以后就很简单了。
‘(‘’)’ 无命名组
最基本的组是由一对圆括号括起来的正则式。比如上面匹配包夹在字母中间的数字的例子中使用的(\d+),我们再回顾一下这个例子:
s = ‘aaa111aaa , bbb222 , 333ccc ‘
re.findall (r’[a-z]+(\d+)[a-z]+’ , s )
[‘111’]
可以看到findall函数只返回了包含在’()’中的内容,而虽然前面和后面的内容都匹配成功了,却并不包含在结果中。
除了最基本的形式外,我们还可以给组起个名字,它的形式是
‘(?P…)’ 命名组
‘(?P’代表这是一个Python的语法扩展’<…>’里面是你给这个组起的名字,比如你可以给一个全部由数字组成的组叫做’num’,它的形式就是’(?P\d+)’。起了名字之后,我们就可以在后面的正则式中通过名字调用这个组,它的形式是
‘(?P=name)’ 调用已匹配的命名组
要注意,再次调用的这个组是已被匹配的组,也就是说它里面的内容是和前面命名组里的内容是一样的。
我们可以看更多的例子:请注意下面这个字符串各子串的特点。
s=’aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg’
我们看看下面的正则式会返回什么样的结果:
re.findall( r’([a-z]+)\d+([a-z]+)’ , s ) # 找出中间夹有数字的字母
[(‘aaa’, ‘aaa’), (‘fff’, ‘ggg’)]
re.findall( r ‘(?P[a-z]+)\d+(?P=g1)’ , s ) #找出被中间夹有数字的前后同样的字母
[‘aaa’]
re.findall( r’[a-z]+(/d+)([a-z]+)’ , s ) #找出前面有字母引导,中间是数字,后面是字母的字符串中的中间的数字和后面的字母
[(‘111’, ‘aaa’), (‘777’, ‘ggg’)]
我们可以通过命名组的名字在后面调用已匹配的命名组,不过名字也不是必需的。
‘\number’ 通过序号调用已匹配的组
正则式中的每个组都有一个序号,序号是按组从左到右,从1开始的数字,你可以通过下面的形式来调用已匹配的组
比如上面找出被中间夹有数字的前后同样的字母的例子,也可以写成:
re.findall( r’([a-z]+)\d+\1’ , s )
[‘aaa’]
结果是一样的。
我们再看一个例子
s=’111aaa222aaa111 , 333bbb444bb33’
re.findall( r’(\d+)([a-z]+)(\d+)(\2)(\1)’ , s ) #找出完全对称的 数字-字母-数字-字母-数字 中的数字和字母
[(‘111’, ‘aaa’, ‘222’, ‘aaa’, ‘111’)]
条件匹配功能(Python2.4以后的re模块)
‘(?(id/name)yes-pattern|no-pattern)’ 判断指定组是否已匹配,执行相应的规则
这个规则的含义是,如果id/name指定的组在前面匹配成功了,则执行yes-pattern的正则式,否则执行no-pattern的正则式。
举个例子,比如要匹配一些形如 [email protected] 的邮箱地址,不过有的写成< [email protected] >即用一对<>括起来,有点则没有,要匹配这两种情况,可以这样写
s=’
导入正则表达式模块
3.1、导入正则表达式模块
import re
3.2、查看正则表达式模块方法
dir(re)
[‘DEBUG’, ‘DOTALL’, ‘I’, ‘IGNORECASE’, ‘L’, ‘LOCALE’, ‘M’, ‘MULTILINE’, ‘S’, ‘Scanner’, ‘T’,’TEMPLATE’, ‘U’, ‘UNICODE’, ‘VERBOSE’, ‘X’, ‘_MAXCACHE’, ‘all‘, ‘builtins‘, ‘doc‘,’file‘, ‘name‘, ‘package‘, ‘version‘, ‘_alphanum’, ‘_cache’, ‘_cache_repl’,’_compile’, ‘_compile_repl’, ‘_expand’, ‘_pattern_type’, ‘_pickle’, ‘_subx’, ‘compile’,’copy_reg’, ‘error’, ‘escape’, ‘findall’, ‘finditer’, ‘match’, ‘purge’, ‘search’, ‘split’,’sre_compile’, ‘sre_parse’, ‘sub’, ‘subn’, ‘sys’, ‘template’]
Match Object对象拥有的方法
1.group([group1,…])
返回匹配到的一个或者多个子组。如果是一个参数,那么结果就是一个字符串,如果是多个参数,那么结果就是一个参数一个item的元组。group1的默认值为0(将返回所有的匹配值).如果groupN参数为0,相对应的返回值就是全部匹配的字符串,如果group1的值是[1…99]范围之内的,那么将匹配对应括号组的字符串。如果组号是负的或者比pattern中定义的组号大,那么将抛出IndexError异常。如果pattern没有匹配到,但是group匹配到了,那么group的值也为None。如果一个pattern可以匹配多个,那么组对应的是样式匹配的最后一个。另外,子组是根据括号从左向右来进行区分的。
>m=re.match(“(\w+) (\w+)”,”abcd efgh, chaj”)
>m.group() # 匹配全部
‘abcd efgh’
>m.group(1) # 第一个括号的子组.
‘abcd’
>m.group(2)
‘efgh’
>m.group(1,2) # 多个参数返回一个元组
(‘abcd’, ‘efgh’)
>m=re.match(“(?P\w+) (?P\w+)”,”sam lee”)
m.group(“first_name”) #使用group获取含有name的子组
‘sam’
m.group(“last_name”)
‘lee’
下面把括号去掉
>m=re.match(“\w+ \w+”,”abcd efgh, chaj”)
>m.group()
‘abcd efgh’
>m.group(1)
Traceback (most recent call last):
File “pyshell#32>”, line 1, in
m.group(1)
IndexError: no such group
If a group matches multiple times, only the last match is accessible:
如果一个组匹配多个,那么仅仅返回匹配的最后一个的。
>m=re.match(r”(..)+”,”a1b2c3”)
>m.group(1)
‘c3’
>m.group()
‘a1b2c3’
Group的默认值为0,返回正则表达式pattern匹配到的字符串
>s=”afkak1aafal12345adadsfa”
>pattern=r”(\d)\w+(\d{2})\w”
>m=re.match(pattern,s)
>print m
None
>m=re.search(pattern,s)
>m
<_sre.SRE_Match object at 0x00C2FDA0>
>m.group()
‘1aafal12345a’
>m.group(1)
‘1’
>m.group(2)
‘45’
>m.group(1,2,0)
(‘1’, ‘45’, ‘1aafal12345a’)
2.groups([default])
返回一个包含所有子组的元组。Default是用来设置没有匹配到组的默认值的。Default默认是”None”,
>m=re.match(“(\d+).(\d+)”,”23.123”)
>m.groups()
(‘23’, ‘123’)
>m=re.match(“(\d+).?(\d+)?”,”24”) #这里的第二个\d没有匹配到,使用默认值”None”
>m.groups()
(‘24’, None)
>m.groups(“0”)
(‘24’, ‘0’)
3.groupdict([default])
返回匹配到的所有命名子组的字典。Key是name值,value是匹配到的值。参数default是没有匹配到的子组的默认值。这里与groups()方法的参数是一样的。默认值为None
>m=re.match(“(\w+) (\w+)”,”hello world”)
>m.groupdict()
{}
>m=re.match(“(?P\w+) (?P\w+)”,”hello world”)
>m.groupdict()
{‘secode’: ‘world’, ‘first’: ‘hello’}
通过上例可以看出,groupdict()对没有name的子组不起作用
常用的正则表达式处理函数
1、re.search
re.search 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回,如果字符串没有匹配,则返回None。
提示:当我们不会用模块方法的时候用help
help(re.search)
search(pattern, string, flags=0)
第一个参数:规则
第二个参数:表示要匹配的字符串
第三个参数:标致位,用于控制正则表达式的匹配方式
实例:下面的例子kuangl
name=”Hello,My name is kuangl,nice to meet you…”
k=re.search(r’k(uan)gl’,name)
ifk:
… printk.group(0),k.group(1)
… else:
… print”Sorry,not search!”
…
kuangl uan
2、re.match
re.match 尝试从字符串的开始匹配一个模式,也等于说是匹配第一个单词
help(re.match)
match(pattern, string, flags=0)
第一个参数:规则
第二个参数:表示要匹配的字符串
第三个参数:标致位,用于控制正则表达式的匹配方式
实例:下面的例子匹配Hello单词
name=”Hello,My name is kuangl,nice to meet you…”
k=re.match(r”(\H….)”,name)
if k:
… print k.group(0),’\n’,k.group(1)
… else:
… print “Sorry,not match!”
…
Hello
Hello
re.match与re.search的区别:re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
3、re.findall
re.findall 在目标字符串查找符合规则的字符串
help(re.findall)
findall(pattern, string, flags=0)
第一个参数:规则
第二个参数:目标字符串
但三个参数:后面还可以跟一个规则选择项
返回的结果是一个列表,建中存放的是符合规则的字符串,如果没有符合规则的字符串呗找到,就会返回一个空值。
实例:查找邮件账号
mail=’[email protected] [email protected] [email protected]’#第3个故意没有尖括号
re.findall(r’(\[email protected]….[a-z]{3})’,mail)
[‘[email protected]’, ‘[email protected]’, ‘[email protected]’]
4、re.sub
re.sub 用于替换字符串的匹配项
help(re.sub)
sub(pattern, repl, string, count=0)
第一个参数:规则
第二个参数:替换后的字符串
第三个参数:字符串
第四个参数:替换个数。默认为0,表示每个匹配项都替换
实例:将空白处替换成-
test=”Hi, nice to meet you where are you from?”
re.sub(r’\s’,’-‘,test)
‘Hi,-nice-to-meet-you-where-are-you-from?’
re.sub(r’\s’,’-‘,test,5) #替换至第5个
‘Hi,-nice-to-meet-you-where are you from?’
5、re.split
re.split 用于来分割字符串
help(re.split)
split(pattern, string, maxsplit=0)
第一个参数:规则
第二个参数:字符串
第三个参数:最大分割字符串,默认为0,表示每个匹配项都分割
实例:分割所有的字符串
test=”Hi, nice to meet you where are you from?”
re.split(r”\s+”,test)
[‘Hi,’, ‘nice’, ‘to’, ‘meet’, ‘you’, ‘where’, ‘are’, ‘you’, ‘from?’]
re.split(r”\s+”,test,3) #分割前三个
[‘Hi,’, ‘nice’, ‘to’, ‘meet you where are you from?’]
6、re.compile
re.compile 可以把正则表达式编译成一个正则对象。可以把那些经常使用的正则表达式编译成正则表达式对象,这样可以提高一定的效率。
help(re.compile)
compile(pattern, flags=0)
第一个参数:规则
第二个参数:标志位
实例:
test=”Hi, nice to meet you where are you from?”
k=re.compile(r’\w*o\w*’) #匹配带o的字符串
dir(k)
[‘copy‘, ‘deepcopy‘, ‘findall’, ‘finditer’, ‘match’, ‘scanner’, ‘search’, ‘split’,’sub’, ‘subn’]
print k.findall(test) #显示所有包涵o的字符串
[‘to’, ‘you’, ‘you’, ‘from’]
print k.sub(lambdam: ‘[‘+m.group(0) +’]’,test) # 将字符串中含有o的单词用[]括起来
Hi, nice [to] meet [you] where are [you] [from]?
python正则表达式的例子
日志分析时,假设给定的字符串:
char str = “10.10.1.1 [2015/04/22 +0800] /ab/cd/?test0=123&test2=234 xxxx”; 要从中获取2015/04/22、/ab/cd/和234等值。
str = “10.10.1.1 [2015/04/22 +0800] /ab/cd/?test0=123&test2=234 xxxx”
print(re.findall(“\d{4}/\d{2}/\d{2}|/\w{2}/\w{2}|(?<=test2=)\d+”, str))
用urllib2、re、os 模块下载文件的脚本
!/usr/bin/env python
importurllib2
importre
importos
URL=’http://image.baidu.com/channel/wallpaper’
read=urllib2.urlopen(URL).read()
pat =re.compile(r’src=\’#\’” //.+?.js”>’)
urls=re.findall(pat,read)
fori inurls:
url=i.replace(‘src=\’#\’” /code>,”).replace(‘”>’,”)
try:
iread=urllib2.urlopen(url).read()
name=os.path.basename(url)
with open(name,’wb’) as jsname:
jsname.write(iread)
except:
printurl,”url error”
from:http://blog.csdn.net/pipisorry/article/details/45476817