第5章 正则表达式

第5章 正则表达式

(1)re.sub(‘ROAD$’, ‘RD. ‘, s)#$匹配在结尾的字符串,^匹配在开头的字符串。re.sub是在s字符串的结尾,查找’ROAD$’,然后用 ‘RD. ‘替换。

(2)re.sub(r’\bROAD\b’, ‘RD. ‘, s)#\b表示一个词的边界在这里。但’\’需要一个’\’进行转意,不然\b会被认为是一个字符。如果不想进行转意要使用一种叫做“生字符串”,方法是在字符串之前加上一个r,如’\t’代表tab字符,但r’\t’它代表两个字符。建议在代有正则表达式的字符串使用“生字符串”,可以避免表达式太复杂而降低了速度。

(3)问号(?)用于匹配至多一次它之前的项;星号(*)用于匹配0或多次之前的项;加号(+)用于匹配1或多次之前的项;点号(.)除了换行符的任意字符。

(4)re模块的核心本质就是search()函数:
re.search(‘^M?M?M?$’, ‘MMMM’)#无法匹配到,因为要求匹配0~3个M开头并结尾的字符,其实就是完全匹配0~3个M,0~3个M不能在字符串的中间出现。
re.search(‘^M?M?M?$’, ”)#可以匹配到,因为可以是0个M!

(5)pattern=’^M?M?M?(CM|CD|D?C?C?C?)$’
这个模式分括号里的内容是一项,不可分割的一组内容,它的内容代表一种可能,用竖线分开(|),可以是:CM,CD或D?C?C?C?。所以:

  1. re.search(pattern, ‘MCM’)#可以匹配到,因为以M开头(开头必须是M?M?M?),并且以CM结尾(结尾必须是CM,CD或D?C?C?C?)
  2. re.search(pattern, ‘MD’)#同样可以匹配到。
  3. re.search (pattern, ‘MMMCCC’)#刚好匹配到所有位。
  4. re.search (pattern, ‘MMMCCCC’)#匹配不到因为位数超了。
  5. re.search (pattern, ‘MCMC’)#匹配不到,因为不能以MC或CMC结尾

(6)pattern = ‘^M{0,3}$’#这个模式是说:匹配开头字符串0至3个M字符,并且结尾也是如此。和’^M?M?M?$’这个模式相同。

  1. {n}精确匹配n次。
  2. {n,}匹配n次至多次。
  3. {,m}至多匹配m次。
  4. {n,m}匹配至少n次至多m次(最大优先)。
  5. {n,m}?匹配至少n次至多m次(最少优先)。

(7)正则表达式分为“精简模式”和“冗余模式”,它们之间的不同是:

  • “冗余模式”的空格、tab和回车被忽略。要想匹配到就要用转意字符。
  • “冗余模式”的注释被忽略。同样是以#号开头,一直到本行的最后。
  • 用之前“精简模式”的例子来演示“冗余模式”,“冗余模式”主要是为了写注释,让以后阅读更方便,:
    >>>pattern = ”’
    ^                                          # beginning of string
    M{0,3}                              # thousands – 0 to 3 Ms
    (CM|CD|D?C{0,3})   # hundreds – 900 (CM), 400 (CD), 0-300 (0 to 3 Cs),
    # or 500-800 (D, followed by 0 to 3 Cs)
    (XC|XL|L?X{0,3})        # tens – 90 (XC), 40 (XL), 0-30 (0 to 3 Xs),
    # or 50-80 (L, followed by 0 to 3 Xs)
    (IX|IV|V?I{0,3})           # ones – 9 (IX), 4 (IV), 0-3 (0 to 3 Is),
    # or 5-8 (V, followed by 0 to 3 Is)
    $                                         # end of string
    ”’
    >>>re.search(pattern, ‘M’, re.VERBOSE)
    可以匹配到内容

(8)
>>> phonePattern = re.compile(r’^(\d{3})-(\d{3})-(\d{4})$’)
>>> phonePattern.search(‘800-555-1212’).groups()
(‘800’, ‘555’, ‘1212’)
groups()方法可以将返回一个元组(tuple),是在正则表达式中定义好的分组,每个分组都是用括号括起来的。
PS:search()和groups()不要连在一起用,因为当没有匹配到内容时,search()会返回None,而None是没有groups()方法的,这时会引发一个异常,如:
>>> pattern = r’^(\d{3})-(\d{3})-(\d{4})-?(\d{4})?$’
>>> re.search(pattern, ‘800-555-12df’).groups()
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
AttributeError: ‘NoneType’ object has no attribute ‘groups’)

(9)方括号[]:

  1. 精确匹配方括号中的一个字符,如[abc]代表仅匹配a或b或c中的一个。
  2. re.sub(str1,str2,str3),在str3中找str1,然后用str2代替。替换所有,而不是第一个找到的。
  3. [^abc]意味着:不包含a,b,c这三个字符。
  4. re.sub(‘([^aeiou])y$’, r’\1ies’, ‘vacancy’)中的\1意味着匹配第一个组(一个括号就是一个组,如同上节的groups()函数一样,只是groups()反回所有组,而\1指 向第一个组),本例中,排除了a,e,i,o,u字符后,第一个组只匹配到了c,并且要以cy结尾,而\1指向c,也就是用cies替换cy。可以有多个 组,用数字向后递推增长就可以了:\2,\3

(10)findall(pattern, string)函数,在string中找到所有符合pattern的字符,并返回一个列表:
>>> import re
>>> re.findall('[0-9]+', '16 2-by-4s in rows of 8') ①
['16', '2', '4', '8'

(11)匹配最短可能的任意字符串(.*?)
>>> re.findall(' s.*? s', "The sixth sick sheikh's sixth sheep's sick.")
[' sixth s', " sheikh's s", " sheep's s"]

(12)

发表评论