个人技术分享


介绍

Python 中的正则表达式(regular expressions, 简称 regex)由 re 模块提供。正则表达式是一种用于匹配字符串的强大工具,常用于文本搜索和处理。以下是一些常用的正则表达式语法及其相关说明:

基本语法

  1. 普通字符: 直接匹配字符本身。

    • 示例: abc 匹配字符串 “abc”。
  2. 点号 (.): 匹配除换行符以外的任意字符。

    • 示例: a.c 匹配 “abc”、“a1c” 等。
  3. 字符集 ([]): 匹配方括号中的任意一个字符。

    • 示例: [abc] 匹配 “a”、“b” 或 “c”。
  4. 字符范围: 在字符集内使用 - 表示范围。

    • 示例: [a-z] 匹配所有小写字母。
  5. 排除字符集 ([^]): 匹配不在方括号内的任意字符。

    • 示例: [^abc] 匹配除 “a”、“b”、“c” 之外的任意字符。
  6. 重复次数:

    • *
      

      : 匹配前面的字符0次或多次。

      • 示例: a* 匹配空字符串、“a”、“aa” 等。
    • +
      

      : 匹配前面的字符1次或多次。

      • 示例: a+ 匹配 “a”、“aa” 等。
    • ?
      

      : 匹配前面的字符0次或1次。

      • 示例: a? 匹配空字符串或 “a”。
    • {m,n}
      

      : 匹配前面的字符至少

      m
      

      次,至多

      n
      

      次。

      • 示例: a{2,4} 匹配 “aa”、“aaa” 或 “aaaa”。
  7. 边界匹配:

    • ^
      

      : 匹配字符串的开头。

      • 示例: ^abc 匹配以 “abc” 开头的字符串。
    • $
      

      : 匹配字符串的结尾。

      • 示例: abc$ 匹配以 “abc” 结尾的字符串。
    • \b
      

      : 匹配单词边界。

      • 示例: \bword\b 匹配独立的单词 “word”。
  8. 特殊字符:

    • \d : 匹配任意数字,等价于 [0-9]
    • \D : 匹配任意非数字字符,等价于 [^0-9]
    • \w : 匹配任意字母数字字符,等价于 [a-zA-Z0-9_]
    • \W : 匹配任意非字母数字字符,等价于 [^a-zA-Z0-9_]
    • \s : 匹配任意空白字符,包括空格、制表符、换行符等。
    • \S : 匹配任意非空白字符。

常用函数

  1. re.match(pattern, string): 从字符串的开头尝试匹配模式。

    • 示例:

      python

      Copy code

      import re
      result = re.match(r'\d+', '123abc')
      if result:
          print(result.group())  # 输出: 123
      
  2. re.search(pattern, string): 搜索整个字符串,返回第一个匹配的结果。

    • 示例:

      python

      Copy code

      result = re.search(r'\d+', 'abc123def')
      if result:
          print(result.group())  # 输出: 123
      
  3. re.findall(pattern, string): 搜索整个字符串,返回所有匹配的结果列表。

    • 示例:

      python

      Copy code

      results = re.findall(r'\d+', 'abc123def456')
      print(results)  # 输出: ['123', '456']
      
  4. re.sub(pattern, repl, string): 替换字符串中所有匹配的子串。

    • 示例:

      python

      Copy code

      result = re.sub(r'\d+', '#', 'abc123def456')
      print(result)  # 输出: abc#def#
      
  5. re.split(pattern, string): 根据模式分割字符串,返回一个列表。

    • 示例:

      python

      Copy code

      import re
      result = re.split(r'\d+', 'abc123def456ghi')
      print(result)  # 输出: ['abc', 'def', 'ghi']
      
  6. re.compile(pattern): 编译正则表达式模式,返回一个正则表达式对象,后续可以使用该对象调用匹配方法。

    • 示例:

      python

      Copy code

      pattern = re.compile(r'\d+')
      result = pattern.match('123abc')
      if result:
          print(result.group())  # 输出: 123
      

捕获组和命名组

  1. 捕获组: 使用圆括号 () 将部分模式括起来,匹配的子串会被捕获到一个组中。

    • 示例:

      python

      Copy code

      match = re.search(r'(\d+)-(\d+)', '123-456')
      if match:
          print(match.group(1))  # 输出: 123
          print(match.group(2))  # 输出: 456
      
  2. 命名组: 使用 (?P<name>...) 语法给捕获组命名,便于后续引用。

    • 示例:

      python

      Copy code

      match = re.search(r'(?P<area_code>\d+)-(?P<number>\d+)', '123-456')
      if match:
          print(match.group('area_code'))  # 输出: 123
          print(match.group('number'))  # 输出: 456
      

非捕获组

有时你可能只想对一部分模式进行分组,但不希望捕获匹配结果。此时可以使用非捕获组 (?:...)

  • 示例:

    python

    Copy code

    match = re.search(r'(?:\d+)-(\d+)', '123-456')
    if match:
        print(match.group(1))  # 输出: 456
    

贪婪匹配和非贪婪匹配

  1. 贪婪匹配: 默认情况下,量词 (*, +, {m,n}) 是贪婪的,会尽可能多地匹配字符。

    • 示例:

      python

      Copy code

      match = re.search(r'<.*>', '<tag>content</tag>')
      if match:
          print(match.group())  # 输出: <tag>content</tag>
      
  2. 非贪婪匹配: 在量词后面加 ? 可以使其变为非贪婪匹配,尽可能少地匹配字符。

    • 示例:

      python

      Copy code

      match = re.search(r'<.*?>', '<tag>content</tag>')
      if match:
          print(match.group())  # 输出: <tag>
      

多行模式和点匹配所有模式

  1. 多行模式 (re.MULTILINE): 使 ^$ 匹配每一行的开头和结尾,而不仅仅是整个字符串的开头和结尾。

    • 示例:

      python

      Copy code

      text = """first line
      second line"""
      matches = re.findall(r'^\w+', text, re.MULTILINE)
      print(matches)  # 输出: ['first', 'second']
      
  2. 点匹配所有模式 (re.DOTALL): 使 . 匹配所有字符,包括换行符。

    • 示例:

      python

      Copy code

      text = "line one\nline two"
      match = re.search(r'line.*', text, re.DOTALL)
      if match:
          print(match.group())  # 输出: line one\nline two
      

示例总结

综合应用上述语法和函数,下面是一个更复杂的示例:

python

Copy code

import re

text = """
John Doe, email: john.doe@example.com, phone: (123) 456-7890
Jane Smith, email: jane.smith@example.com, phone: (987) 654-3210
"""

# 提取所有的 email 地址
emails = re.findall(r'\b[\w.-]+?@\w+?\.\w+?\b', text)
print("Emails:", emails)

# 提取所有的电话号码
phones = re.findall(r'\(\d{3}\) \d{3}-\d{4}', text)
print("Phones:", phones)

# 提取姓名