Python 正则表达式(转义问题)
先说一个比较囧的事情:在写虾米音乐试听下载器的时候遇到一个问题,因为保存的文件都是用音乐的标题命名的,所以碰到一些诸如「対峙/outborder」等含有非法字符(哼哼,说的就是你→_→Windows)的标题的时候,就会保存失败。于是我想起了迅雷的解决方法:把所有的非法字符替换成下划线。
于是就引入了正则表达式的使用。一番搜索囫囵吞枣后,我写下了这样的函数:
defsanitize_filename(filename): returnre.sub('[\/:*?<>|]','_',filename)
最近意识到了这个函数里的好多问题:
- Python和Shell不同,无论单引号还是双引号,反斜杠都是转义符。走狗屎运的是,Python对于没意义的转义\/的处理是保持原样。
- 即便如此,sanitize_filename('\\/:*?<>|')依旧返回\_______而不是全部都是下划线。
于是感觉得正正经经看看文档了。
Rawstrings
看了文档后才意识到,Python正则表达式模块的转义是独立的。例如匹配一个反斜杠字符需要将参数写成:'\\\\':
Python将字符串转义:\\\\被转义为\\
re模块获得传入的\\将其解释为正则表达式,按照正则表达式的转义规则将其转义为\
如此麻烦的前提下,RawString就大有作为了,顾名思义就是(除了结尾的反斜杠)不会被转义的字符串。于是匹配一个反斜杠字符就可以写作r'\\'。
所以上面的sanitize_filename改成了:
defsanitize_filename(filename): returnre.sub(r'[\\/:*?<>|]','_',filename)
Regex和Match
于是正经看看re模块吧~以下为流水帐,供急性子观看。
Python的正则表达式模块re中主要的对象其实是这俩:
正则表达式RegexObject
匹配MatchObject
RegexObject是正则表达式对象,所有matchsub之类的操作都归它所有。由re.compile(pattern,flag)生成。
>>>email_pattern=re.compile(r'\w+@\w+\.\w+') >>>email_pattern.findall('Myemailisabc@def.comandhisisuser@example.com') ['abc@def.com','user@example.com']
其中的方法:
search从任意字符开始匹配,返回MatchObject或者None
match从第一个字符开始匹配,返回MatchObject或者None
split返回由匹配分割的List
findall返回所有匹配的List
finditr返回MatchObject的迭代器
sub返回替换后的字符串
subn返回(替换后的字符串,替换次数)
re模块里提供的函数如re.subre.matchre.findall实际上都可以认为是一种省去直接创建正则表达式对象的捷径。而由于RegexObject对象本身可以反复使用,这也是它相对于这些捷径函数的优势所在。
MatchObject则是匹配对象,表示一次正则表达式匹配的结果。由RegexObject的一些方法返回。匹配对象永远是True的,另外还有一大堆用来取得正则表达式中分组(group)相关信息的方法。
>>>forminre.finditer(r'(\w+)@\w+\.\w+','Myemailisabc@def.comandhisisuser@example.com'): ...print'%d-%d%s%s'%(m.start(0),m.end(0),m.group(1),m.group(0)) ... 12-23abcabc@def.com 35-51useruser@example.com
参考
- ThePythonStandardLibrary:http://docs.python.org/2/library/re.html