博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Using Regular Expressions in Python
阅读量:6300 次
发布时间:2019-06-22

本文共 4914 字,大约阅读时间需要 16 分钟。

1. 反斜杠的困扰(The Backslash)

  有时候需要匹配的文本带有'\',如'\python',因为正则表达式有些特殊字符有特殊意义,所以需要前面加上'\'来消除特殊意义,这里匹配的正则表达式是'\\python',这时候如果要编译这个正则表达式需要re.compile('\\\\python'),因为在传递字符串的时候python本身就需要用'\\'来表示'\',也就造成了反斜杠的泛滥。

  使用前缀'r'可以解决这个问题:’r'之后的'\'只是这个字符本身而没有特殊意义,比如r'\n'表示两个符号'\'和'n',而原来'\n'表示换行符,所以可以写成re.compile('\\python')

 

2. match的几种methods

match(): 判断RE是否从第一个字符开始匹配

search(): 判断是否从任意一个位置匹配(不管是否从第一个字符开始)

findall(): 找到RE匹配的所有子字符串,并以list的形式返回

finditer(): 找到RE匹配的所有子字符串,并以iterator的形式返回

1 >>> p = compile('[a-z]+') 2 >>> print p.match("") 3 None 4  5 >>> m = p.match('tempo') 6 >>> m.group() 7 'tempo' 8 >>> m.start(), m.end() 9 (0, 5)10 >>> m.span()11 (0, 5)12 13 >>> m = p.search('::: message')14 >>> m.group()15 'message'16 17 >>> p = re.compile('\d+')18 >>> it = p.finditer('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')19 >>> for match in it:20 ...     print match.group()21 ...22 (0, 2)23 (22, 24)24 (29, 31)

 

 

3.

'|': “或”,A|B表示匹配A或者B

'^': 匹配行的开头,一般情况下只会匹配字符串的开头,如果在MULTILINE模式下则可以匹配每行的开头

1 >>> print re.search('^From', 'From Here to Eternity')2 <_sre.SRE_Match object at 0x...>3 >>> print re.search('^From', 'Reciting From Memory')4 None

 

 

'\A': 只匹配字符串的开头

 

'$': 匹配行的末尾,一般情况下只会匹配字符串的末尾,如果在MULTILINE模式下则可以匹配每个换行符

'Z': 只匹配字符串的末尾

 

'\b': 单词的边界,即单词的开头或者末尾,可以是空格或者非字母数字的字符

1 >>> p = re.compile(r'\bclass\b')2 >>> print p.search('no class at all')3 <_sre.SRE_Match object at 0x...>4 >>> print p.search('the declassified algorithm')5 None6 >>> print p.search('one subclass is')7 None

 

  注意上面用来编译的正则前面要带'r',因为在Python中'\b'是退格键,如下:

1 >>> p = re.compile('\bclass\b')2 >>> print p.search('no class at all')3 None4 >>> print p.search('\b' + 'class' + '\b')5 <_sre.SRE_Match object at 0x...>

 

'\B': 匹配不是单词边界

 

4. Grouping

  用'()'括起来表示分组,比如(ab)*可以匹配ab0次或者更多次。

  分组是有编号的,0表示整个RE,从左往右编号依次加一,只要看左括号的位置就行

 

1 >>> p = re.compile('(a(b)c)d')2 >>> m = p.match('abcd')3 >>> m.group(0)4 'abcd'5 >>> m.group(1)6 'abc'7 >>> m.group(2)8 'b'

 

 

5. Non-capturing Groups

  ()里面跟着?:的是non-capturing group,一般用于一些分组后面不需要用到的时候

 

1 >>> m = re.match("([abc])+", "abc")2 >>> m.groups()3 ('c',)4 >>> m = re.match("(?:[abc])+", "abc")5 >>> m.groups()6 ()

  原来编号1的分组在加上?:之后被忽略了,可以用在筛选一些没有用的分组。比较令人疑惑的是第2行m.groups()为什么是'c',这里我觉得应该是贪婪模式尽量往后找的原因

 

6. Named Groups

  分组过多的时候编号难以记住,可以给分组加上一个名字,相当于一个“标签”,后面引用的时候可以直接通过名字来引用,用法是(?P<name>...)

1 >>> p = re.compile(r'((?P
\b\w+\b))')2 >>> m = p.search( '(((( Lots of punctuation )))' )3 >>> m.group('word')4 'Lots'5 >>> m.group(1)6 'Lots'

 

  还可以用来搜索与前面重复的字段:

1 >>> p = re.compile(r'(?P
\b\w+)\s+(?P=word)')2 >>> p.search('Paris in the the spring').group()3 'the the'

 

7. Lookahead Assertions

  (?=...) 需要在这个位置匹配括号里面之后的内容,匹配成功即可,不会消耗字符串的内容。

  (?!...) 与前一个相反,不能匹配括号里面之后的内容才能匹配成功,不会消耗字符串的内容。

  如在匹配带有扩展名的文件的时候,如果想要排除掉带有后缀.bat和.exe的文件,可以用 .*[.](?!bat$|exe$).*$

8. Splitting Strings

1 >>> p = re.compile(r'\W+')2 >>> p2 = re.compile(r'(\W+)')3 >>> p.split('This... is a test.')4 ['This', 'is', 'a', 'test', '']5 >>> p2.split('This... is a test.')6 ['This', '... ', 'is', ' ', 'a', ' ', 'test', '.', '']

 

 

  如果使用括号将匹配内容括起来,那么在分割的时候匹配内容也会作为分割的一部分,否则匹配内容会被忽略。如上面通过空格将单词分开,加了括号之后空格也会记录为结果。

  .split()函数可以加进参数maxsplit表示最多分割几段,如:

 

1 >>> p = re.compile(r'\W+')2 >>> p.split('This is a test, short and sweet, of split().')3 ['This', 'is', 'a', 'test', 'short', 'and', 'sweet', 'of', 'split', '']4 >>> p.split('This is a test, short and sweet, of split().', 3)5 ['This', 'is', 'a', 'test, short and sweet, of split().']

 

9. Search and Replace

  p = re.compile('...') , p.sub(replacement, string, [count = 0])

  string是原来用来被查找替换的字符串,replacement是查找到之后替换的内容,count是最多替换的个数,默认是0表示全部替换

1 >>> p = re.compile( '(blue|white|red)')2 >>> p.sub( 'colour', 'blue socks and red shoes')3 'colour socks and colour shoes'4 >>> p.sub( 'colour', 'blue socks and red shoes', count=1)5 'colour socks and red shoes'

 

  subn()使用方法类似,但是会同时返回找到替换的个数

1 >>> p = re.compile( '(blue|white|red)')2 >>> p.subn( 'colour', 'blue socks and red shoes')3 ('colour socks and colour shoes', 2)4 >>> p.subn( 'colour', 'no colours at all')5 ('no colours at all', 0)

 

 

  之前有命名分组的使用方法,(?P<name>...),后面想替换成这个分组的内容可以用\g<name>来替换,或者替换成第2组的内容可以用\2,但是替换成第2组内容后面再加上一个0就会写成\20,会与第20组产生误会,所以有另一个写法是\g<2>,下面例子用了这3种方法,将所有的section替换成subsection

1 >>> p = re.compile('section{ (?P
[^}]* ) }', re.VERBOSE)2 >>> p.sub(r'subsection{\1}','section{First}')3 'subsection{First}'4 >>> p.sub(r'subsection{\g<1>}','section{First}')5 'subsection{First}'6 >>> p.sub(r'subsection{\g
}','section{First}')7 'subsection{First}'

 

 

  还有一种更复杂的方法是用一个函数进行替换,每次会对match到的内容进行一定的操作,如下面将数字转化为16进制的时候,首先将match到的内容作为参数传进函数进行处理再返回16进制数

1 >>> def hexrepl(match):2 ..."Return the hex string for a decimal number"3 ...value = int(match.group())4 ...return hex(value)5 ...6 >>> p = re.compile(r'\d+')7 >>> p.sub(hexrepl, 'Call 65490 for printing, 49152 for user code.')8 'Call 0xffd2 for printing, 0xc000 for user code.'

 

转载于:https://www.cnblogs.com/jolin123/p/3857711.html

你可能感兴趣的文章
Xamarin Alpha预览
查看>>
iOS:UITableViewCell自定义单元格
查看>>
.NET Framework 4 和 .NET Framework 4 Client Profile
查看>>
麦当劳理论(转转转)
查看>>
视图与暂时表
查看>>
C# 视频监控系列(6):服务器端——封装API(上) [HikServer.dll]
查看>>
Less动态css-演讲稿(ppt)
查看>>
SQLite.NET提供程序的选择
查看>>
js window.open()实现打印,如何在关闭打印窗口时刷新父窗口
查看>>
KSFramework:集成U3D热重载框架 - README
查看>>
pipe row的用法, Oracle split 函数写法.
查看>>
WPF快速指导4:数据绑定之绑定方向与自定义转换器
查看>>
C++问题:if( input.rdstate() & std::ios::failbit )
查看>>
Winform开发框架中实现多种数据库类型切换以及分拆数据库的支持
查看>>
Socket开发框架之数据加密及完整性检查
查看>>
通过二进制头识别文件类型
查看>>
从一个集合中查找最大最小的N个元素——Python heapq 堆数据结构
查看>>
1.6. FAQ
查看>>
[LeetCode] Minimum Size Subarray Sum
查看>>
Centos 搭建Mysql-Proxy 读写分离
查看>>