Using Regular Expressions in Python

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 None
6 >>> 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 None
4 >>> 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<word>\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<word>\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<name> [^}]* ) }, re.VERBOSE)
2 >>> p.sub(rsubsection{\1},section{First})
3 subsection{First}
4 >>> p.sub(rsubsection{\g<1>},section{First})
5 subsection{First}
6 >>> p.sub(rsubsection{\g<name>},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.

 

Using Regular Expressions in Python,布布扣,bubuko.com

Using Regular Expressions in Python

上一篇:java多线程执行问题


下一篇:unity iOS本地代码总结(一)