对正则知识的整理,方便自己以后复习。这一部分内容,自己必须耐下心来好好整理一下。对于正则表达式每个符号的含义都需要进行记忆。

例子 1:匹配文本中特定模式的电话号

  1. import re
  2. # compile()返回一个 Regex 模式对象
  3. phoneNumRegex = re.compile(r'\d{3}-\d{3}-\d{4}')
  4. # search()方法将返回一个 Match 对象
  5. mo = phoneNumRegex.search('My number is 415-555-4242.')
  6. # group()会返回匹配的结果
  7. print('Phone number found: ' + mo.group())

正则表达式匹配过程可视化网站:https://www.regexpal.com/

(分组)例子 2: 将区号从电话号码中分离

  1. import re
  2. phoneNumRegex = re.compile(r'(\d{3})-(\d{3}-\d{4})')
  3. mo = phoneNumRegex.search('My number is 415-555-4242.')
  4. # 向 group() 方法传入 0 或不传入参数,将返回整个匹配的文本
  5. print('mo.group(): ' + mo.group())
  6. print('mo.group(0): ' + mo.group(0))
  7. # 向 group() 匹配对象方法传入整数 1 或 2,就可以取得匹配文本的不同部分
  8. print('mo.group(1): ' + mo.group(1))
  9. print('mo.group(2): ' + mo.group(2))
  10. # mo.group(): 415-555-4242
  11. # mo.group(0): 415-555-4242
  12. # mo.group(1): 415
  13. # mo.group(2): 555-4242

(管道)用管道匹配多个分组

  • 字符 | 称为“管道”。希望匹配许多表达式中的一个时,就可以使用它
  • 如果 Batman 和 Tina Fey 都出现在被查找的字符串中,第一次出现的匹配文本, 将作为 Match 对象返回 ```python import re

heroRegex = re.compile(r’Batman|Tina Fey’)

mo1 = heroRegex.search(‘Batman and Tina Fey.’) print(mo1.group()) # Batman

mo2 = heroRegex.search(‘Tina Fey and Batman.’) print(mo2.group()) # Tina Fey

  1. ```python
  2. import re
  3. batRegex = re.compile(r'Bat(man|mobile|copter|bat)')
  4. mo = batRegex.search('Batmobile lost a wheel')
  5. print(mo.group()) # Batmobile
  6. # 返回第一个括号分组内匹配的文本
  7. print(mo.group(1)) # mobile
  1. import re
  2. # 字符?表明它前面的分组在这个模式中是可选的
  3. # 不论这段文本在不在,正则表达式都会认为匹配
  4. batRegex = re.compile(r'Bat(wo)?man')
  5. mo1 = batRegex.search('The Adventures of Batman') # Batman
  6. print(mo1.group())
  7. mo2 = batRegex.search('The Adventures of Batwoman') # Batwoman
  8. print(mo2.group())
  1. import re
  2. # 字符*匹配零次或多次
  3. batRegex = re.compile(r'Bat(wo)*man')
  4. mo1 = batRegex.search('The Adventures of Batman')
  5. print(mo1.group())
  6. mo2 = batRegex.search('The Adventures of Batwoman') # Batwoman
  7. print(mo2.group())
  8. mo3 = batRegex.search('The Adventures of Batwowowowoman')
  9. print(mo3.group())
  1. import re
  2. # 字符+匹配一次或多次
  3. batRegex = re.compile(r'Bat(wo)+man')
  4. mo1 = batRegex.search('The Adventures of Batman')
  5. if mo1 is None:
  6. print(None)
  7. mo2 = batRegex.search('The Adventures of Batwoman') # Batwoman
  8. print(mo2.group())
  9. mo3 = batRegex.search('The Adventures of Batwowowowoman')
  10. print(mo3.group())
  1. # 用花括号匹配特定次数
  2. # 如果想要一个分组重复特定次数,就在正则表达式中该分组的后面
  3. import re
  4. haRegex = re.compile(r'(Ha){3}')
  5. mo1 = haRegex.search('HaHaHa')
  6. print(mo1.group())
  7. mo2 = haRegex.search('Ha')
  8. print(mo2 is None)

Python 的正则表达式默认是“贪心”的,即会尽可能匹配最长的字符串。

修改为非贪心( 在结束的花括号后跟一个问号 ):

  1. import re
  2. greedyHaRegex = re.compile(r'(Ha){3,5}')
  3. mo1 = greedyHaRegex.search('HaHaHaHaHa')
  4. print(mo1.group())
  5. nongreedyHaRegex = re.compile(r'(Ha){3,5}?')
  6. mo2 = nongreedyHaRegex.search('HaHaHaHaHa')
  7. print(mo2.group())

search() 和 findall() 的区别:

  • search() 将返回一个Match 对象,包含被查找字符串中的“第一次”匹配的文本
  • findall() 方法将返回一个 list,包含被查找字符串中的所有匹配
    • 如果调用在一个没有分组的正则表达式上, findall() 将返回一个匹配字符串的列表
    • 如果调用在一个有分组的正则表达式上,方 法 findall() 将返回一个字符串的元组的列表(每个分组对应一个字符串)
      ```python import re

phoneNumRegex = re.compile(r’\d\d\d-\d\d\d-\d\d\d\d’) # has no groups print(phoneNumRegex.findall(‘Cell: 415-555-9999 Work: 212-555-0000’))

[‘415-555-9999’, ‘212-555-0000’]

  1. ```python
  2. import re
  3. phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)') # has groups
  4. print(phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000'))
  5. # [('415', '555', '9999'), ('212', '555', '0000')]

插入字符和美元字符

可以用 ^ 和 $ 字符来卡范围。例如, r'^Hello' 表示匹配以 Hello 开头的内容, r'\d$' 匹配以数字结束的内容, r'^\d+$' 匹配从开始到结束都是数字的字符串。

用句点字符匹配换行

通过传入 re.DOTALL 作为 re.compile()的第 二个参数,可以让句点字符匹配所有字符,包括换行字符

  1. import re
  2. noNewlineRegex = re.compile('.*')
  3. print(noNewlineRegex.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group())
  4. newlineRegex = re.compile('.*', re.DOTALL)
  5. print(newlineRegex.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group())

不区分大小写的匹配

  • 要让正则表达式 不区分大小写,可以向 re.compile() 传入 re.IGNORECASEre.I,作为第二个参数。

用 sub()方法替换字符串

管理复杂的正则表达式

有时候正则表达式会很长很复杂,这时候要对正则表达式的每个部分进行说明,则可以用下面的方法:

你可以告诉 re.compile(),忽略正则表达式字符 串中的空白符和注释,从而缓解这一点。要实现这种详细模式,可以向 re.compile() 传入变量 re.VERBOSE,作为第二个参数。

例如:

  1. phoneRegex = re.compile(r'((\d{3}|\(\d{3}\))?(\s|-|\.)?\d{3}(\s|-|\.)\d{4}(\s*(ext|x|ext.)\s*\d{2,5})?)')

可改为:

  1. phoneRegex = re.compile(r'''(
  2. (\d{3}|\(\d{3}\))? # area code
  3. (\s|-|\.)? # separator
  4. \d{3} # first 3 digits
  5. (\s|-|\.) # separator
  6. \d{4} # last 4 digits
  7. (\s*(ext|x|ext.)\s*\d{2,5})? # extension
  8. )''', re.VERBOSE)

组合使用 re.IGNOREC ASE、re.DOTALL 和 re.VERBOSE

re.compile()函数只接受一 个值作为它的第二参数。可以使用管道字符(|)将变量组合起来,从而绕过这个限 制。管道字符在这里称为“按位或”操作符。

  1. someRegexValue = re.compile('foo', re.IGNORECASE | re.DOTALL | re.VERBOSE)

image.png