正则表达式就原理来讲,只有一点点东东,就是一个状态机,只能用在上下文无关文法的环境。
但是它使用还是非常灵活的,那些厉害的,能够玩出花来,工作效率提高很多。
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 | 
| ? | 匹配1次或者0次前面出现的正则表达式 | 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 | 
| \d | 匹配任何十进制数字 | data\d.txt | 
| \D | 不匹配任何十进制数字 | |
| \w | 等价于[a-zA-Z0-9] | [a-zA-Z]\w+ | 
| \s | 匹配任何空格字符[\n\t\r\v\f] | of\sthe | 
| \S | 不匹配任何空格字符[^\n\t\r\v\f] | \bthe\b | 
| \b | 匹配任何单词边界 | |
| \B | 与\b相反 | |
| \N | 匹配已保存的自组N | |
| \c | 逐字匹配任何特殊字符c (就是转译) | \. \\ \* | 
| \A(\Z) | 匹配字符串的开始(结尾) | |
| 扩展表示法 | ||
| (?iLmsaux) | 在正则表达式中嵌入一个或者多个特殊标记参数(或者通过函数方法) i:不区分大小匹配 m:多行文本 ^ $会去尝试匹配每一行的起始和结束 \A \Z不会 s:单行文本 a:ascii 文本 u:unicode文本 
 | (?x) (? im) | 
| (?:...) | 表示一个匹配不用保存的分组 | (?:\w+\.)* | 
| (?P<name>...) | 像一个仅由name标识而不是数字id标识的正则分组匹配 | (?P<data>) | 
| (?P=name) | 在同一字符串中匹配由(?P<name>)分组的之前文本 | (?p=data) | 
| (?#....) | 表示注释,所有的内容都被忽略 | (?#comment) | 
| (?=....) | 匹配条件是如果...出现在之后的位置,而不使用输入字符串,称作正向前视断言 | (?=.com) | 
| (?!....) | 匹配条件是如果...不出现在之后的位置,而不使用输入字符串,称作负向前视断言 | (?!.net) | 
| (?<=...) | 匹配条件是如果...出现在之后的位置,而不使用输入字符串,称作正向后视断言 | (?<=800-) | 
| (?<!...) | 匹配条件是如果...不出现在之后的位置,而不使用输入字符串,称作负向后视断言 | (?<!192\.168\.) | 
| (?(id|name)Y|N) | 如果分组所提供的id或者name存在,就返回正则表达式的条件匹配Y, 如果不存在就返回N;N是可选项 | (?(1)y|x) | 
2.re模块核心函数
| compile(pattern,flags=0) | 使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象 | 
| match(pattern,string,flags=0) | 尝试使用带有可选标记的正则表达式的模式来匹配字符串,如果匹配成功,就返回匹配对象 如果失败,就返回None | 
| search(pattern,string,flags=0) | 使用可选标记搜索字符串中第一次出现的正则表达式模式,如果成功就返回匹配对象 如果失败,就返回None | 
| findall(pattern,string[,flags]) | 查找字符串中所有非重复出现的正则表达式模式,返回一个匹配列表 | 
| finditer(pattern,string,[,flags]) | 与findall函数相同,但返回的不是一个列表,而是一个iter, 对于每一次匹配,迭代器都返回一个匹配对象 | 
| split(pattern,string,max=0) | 根据正则表达式的模式分隔符,split函数将字符串分割为列表,然后返回成功匹配的列表, 分割最多操作max次 | 
| sub(pattern,repl,string,count=0) | 使用repl替换所有正则表达式的模式在字符串中出现的位置,除非定义了count,否则, 就替换所有出现的位置 | 
| purge() | 清除隐式编译的正则表达式 | 
| group(num=0) | 返回整个匹配对象或者编号为num的特定子组 | 
| groups(default=None) | 返回一个包含所有匹配子组的元祖,如果没有匹配的就返回一个空tuple | 
| groupdict(defalut=None) | 返回一个包含所有匹配的命名自组的字典,所有的子组名词作为字典的键 | 
| re.I, re.IGNORECASE | 不区分大小写的匹配 | 
| re.L, re.LOCAL | 根据所使用的本地语言环境通过 \w \W \b \B \s \S 实现匹配 | 
| re.M re.MULTILINE | ^和$分别匹配目标字符串行的起始和结尾,而不是严格匹配整个字符串本身的起始和结尾 | 
| re.S re.DOTALL | "."(点号)通常匹配除了\n(换行符)之外的所有单个字符; 该标记表示"."(点号)能够匹配全部字符 | 
| re.X re.VERBOSE | 通过反斜杠转义,否则所有空格加上#(以及在该行中所有后续文字)都被忽略, 除非在一个字符类中或者允许注释并且提高可读性。 | 
3.MatchObject 常用函数:
用re.match(pattern,string,flag)和re.search(pattern,string,flag)匹配出来的都是Matchobject。介绍matchobject有个比较常用的方法,觉得非常的实用。
1.start(groupnum=0)
这个函数返回 某个匹配结果的某个groupnum开始的匹配的位置.
>>> string=‘xyz123123xyz‘ >>> pattern=‘(123)‘ >>> m=re.search(pattern,string) >>> m.group(0) ‘123‘ >>> >>> m.group(1) ‘123‘ >>> m.start(1) #这里就会返回第一次匹配到那个123在整个xyz123123xyz中的起始位置 3
2.end(),endpos(groupnum)
这个同上,只不过是返回结果是结束位置。
3.group(num=0),groups(),groupdict()
这几个函数用于返回匹配串种被额外分组保存的部分,group(0)是整个匹配的结果,从1开始是额外保存分组的部分。groups()返回额外保存的分组部分
groupdict()返回groupname:groupvalue这种字典
>>> pattern=‘1([abc]+)3‘
>>> string=‘1bc3‘
>>> m=re.search(pattern,string)
>>> m.group(0)
‘1bc3‘
>>> m.group(1)
‘bc‘
>>> m.groups()
(‘bc‘,)
>>> m.groupdict()
{}
groupdict()
>>> string
‘1bc3‘
>>> pattern=r‘1(?P<g1>[abc]+)3‘
>>> m=re.search(pattern,string)
>>> m
<_sre.SRE_Match object at 0x00BD2E20>
>>> m.groupdict()
{‘g1‘: ‘bc‘}
4.expand(stringtemplate)
比如m.group(1)==bc
那么m.expand(r"xxxx \1 zzzzz")会返回 xxxx bc zzzzz ,\1的地方会用group(1)的值替代
和这个函数功能类似的还有re.sub(pattern,replacement,string,flag) 在string中符合pattern的地方用replacement 替换
4.re模块常用函数
预编译
re.compile(pattern,flags) 这个方法用于将一个正则表达式先编译成内部表示,以加快后面的使用效率。
匹配
re.match(pattern,string,flags), re.search(pattern,string,flags) 这两个函数用于匹配 ,区别在于match必须从string的起始位置开始匹配,如果起始位置不匹配,就算是没有匹配了,search则是返回string中第一次匹配成功的字符串。
查找
re.findall(pattern,string,flags), re.finditer(pattern,string,flags) 返回所有匹配的部分,findall比较费点内存,finditer节约点内存。
切分
re.split(pattern,string),将string切分,只要是匹配pattern的地方都切分。
>>> string="a12b3223d55" >>> pattern=r‘[\d]+‘ >>> s=re.split(pattern,string) >>> s [‘a‘, ‘b‘, ‘d‘, ‘‘]
替换
re.sub(pattern,repl,string[,count,flags])
>>> string="a12b3223d55" >>> pattern=r‘[\d]+‘ >>> >>> s=re.sub(pattern,‘ hello ‘,string) >>> s ‘a hello b hello d hello ‘
5.几个可能比较少用的点
1.分组的使用
常用的列子就是日期格式的变换了
yyyy/mm/dd 变换到 dd/mm/yyy
string=‘2016/6/24‘
pattern=r‘([\d]{4})/([\d]{1,2})/([\d]{1,2})‘
a=re.match(pattern,string)
a.groups()-----> (‘2016‘, ‘6‘, ‘24‘)
格式转换:
re.sub(pattern,r‘\3-\2-\1‘,string) -----> ‘24-6-2016‘
2.向前看肯定、想前看否定,向后看肯定、向后看否定( 行话叫“环视”)
string=‘abcdefg‘
向前看肯定:pattern=‘cd(?=ef)‘ 这个表达式的意思是匹配cd,但是cd后面必须跟着‘ef‘ re.search(pattern,string) 返回 ‘cd‘
向前看否定:pattern=‘cd(?!ef)‘ 这个表达式的意思是匹配cd,但是cd后面必须不能跟着‘ef‘ re.search(pattern,string) 返回 None
另外两个不写了,差不多的意思,看着是不是有点编译原理里面文法分析的LR(K) 算法的那个K的意思,可是这个不是,正则只能用在词法分析阶段。因为他不跟踪上下文信息。
3.分组时,?+*在()里面和在()外面的差别
。。。。。。。。
原文:http://www.cnblogs.com/hi0xcc/p/5608054.html