掌握 Python 正则表达式:100个实用技巧与案例。

Structural Pattern Matching in Python I

正则表达式(regex 或 regexp)是 Python 中用于模式匹配与文本处理的强大工具。其语法简洁灵活,能够精准描述字符串中的各类模式,在数据提取、格式验证、文本清洗等场景中发挥着重要作用。

本文系统梳理了 Python 正则表达式的高级特性与一系列使用技巧,帮助读者快速掌握!

一、特性

1.正则表达式简介

正则表达式是定义搜索模式的字符序列,是用于字符串匹配和处理的多功能工具。在 Python 中,re 模块提供了对正则表达式的支持。

import re

2.基本模式

2.1 字面字符
pattern = re.compile(r'hello')
result = pattern.match('hello world')
print(result.group())  # 输出:'hello'
2.2 字符类
pattern = re.compile(r'[aeiou]')
result = pattern.findall('hello world')
print(result)  # 输出:['e', 'o', 'o']
2.3 通配符 .
pattern = re.compile(r'he..o')
result = pattern.match('hello world')
print(result.group())  # 输出:'hello'

3.量词

3.1 *+?
pattern = re.compile(r'ab*c')
result = pattern.match('ac')
print(result.group())  # 输出:'ac'

4.锚点

4.1 ^(字符串开头)和 $(字符串结尾)
pattern = re.compile(r'^hello')
result = pattern.match('hello world')
print(result.group())  # 输出:'hello'

5.字符转义

pattern = re.compile(r'\d+')  # 匹配一个或多个数字
result = pattern.match('123')
print(result.group())  # 输出:'123'

6.字符集和范围

pattern = re.compile(r'[a-z]')
result = pattern.findall('Hello World')
print(result)  # 输出:['e', 'l', 'l', 'o', 'o', 'r', 'l', 'd']

7.分组和捕获

pattern = re.compile(r'(\d+)-(\d+)-(\d+)')
result = pattern.match('2023-11-25')
print(result.groups())  # 输出:('2023', '11', '25')

8.高级模式

8.1 前瞻和后顾
pattern = re.compile(r'(?<=@)\w+')
result = pattern.findall('user@example.com')
print(result)  # 输出:['example']
8.2 非捕获组
pattern = re.compile(r'(?:\d+)-(\d+)-(\d+)')
result = pattern.match('2023-11-25')
print(result.groups())  # 输出:('11', '25')

9.Python 中正则表达式的使用

9.1 match 与 search
pattern = re.compile(r'world')
result = pattern.match('hello world')
print(result)  # None


result = pattern.search('hello world')
print(result.group())  # 输出:'world'
9.2 findall
pattern = re.compile(r'\d+')
result = pattern.findall('There are 25 apples and 30 oranges')
print(result)  # 输出:['25', '30']

10.替换和替换操作

pattern = re.compile(r'\d+')
result = pattern.sub('X', 'There are 25 apples and 30 oranges')
print(result)  # 输出:'There are X apples and X oranges'

11.不区分大小写

pattern = re.compile(r'hello', re.IGNORECASE)
result = pattern.match('HeLLo World')
print(result.group())  # 输出:'HeLLo'

二、有效使用正则表达式的100个技巧

1.通用技巧

  1. 使用原始字符串(如 r'\d+')以避免意外的转义字符。

  2. 若需多次使用正则表达式模式,建议编译模式以提升性能。

    import re
    
    # 不编译模式(重复编译)
    for _ in range(1000):
        result = re.match(r'\d+', '123')
    
    # 编译模式(仅编译一次)
    pattern = re.compile(r'\d+')
    for _ in range(1000):
        result = pattern.match('123')
  3. 针对多种情况测试正则表达式,确保其正确性。

    import re
    
    # 示例:匹配电子邮件地址
    pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b')
    
    # 测试用例
    test_cases = [
        "user@example.com",             # 有效的电子邮件
        "user@company.co.uk",           # 带国家代码的有效电子邮件
        "name123@sub.domain.org",       # 带子域名的有效电子邮件
        "invalid_email@no_tld",         # 无效的电子邮件(无顶级域名)
        "@missing_username.com",        # 无效的电子邮件(无用户名)
        "user@invalid_domain",          # 无效的电子邮件(域名无效)
        "name@server.c",                # 无效的电子邮件(顶级域名过短)
        "name@server.with_space.com",   # 无效的电子邮件(域名含空格)
        "user@@double_at.com",          # 无效的电子邮件(含两个@)
        "user@excessive_length_domain." + "a" * 255# 无效的电子邮件(域名过长)
    ]
    
    # 用每个测试用例测试模式
    for email in test_cases:
        match = pattern.match(email)
        print(f"{email}:{'有效' if match else '无效'}")

2.字符类

  1. 利用字符类(如 [a-z])匹配指定范围内的任意字符。

  2. 使用否定(字符类中的 ^)匹配不在指定范围内的字符(如 [^0-9] 匹配非数字)。

3.量词

  1. 需匹配最小内容时,优先使用非贪婪量词(*?+?)。

  2. 使用贪婪量词(*+)时需谨慎,避免意外的长匹配。

4.锚点和边界

  1. 使用 ^ 和 $ 分别将模式锚定到行的开头和结尾。

  2. 利用单词边界(\b)匹配完整单词。

5.选择和分组

  1. 使用选择(|)匹配多个模式(如 cat|dog)。

  2. 需对模式的特定部分(而非整个模式)应用量词(*+{})或选择(|)时,分组非常有用。

6.字符转义

  1. 熟悉常见的字符转义(\d\w\s),分别用于匹配数字、单词字符和空白字符。

  2. 若需匹配特殊字符(如 .),需转义(如 \.)。

7.环视

  1. 使用正向前瞻((?=...))匹配后面跟有特定模式的内容。

  2. 利用负向前瞻((?!...))匹配后面不跟特定模式的内容。

8.替换

  1. 使用捕获组在替换中提取并引用匹配字符串的部分内容。

    import re
    
    # 示例:替换日期格式
    pattern = re.compile(r'(\d{1,2})/(\d{1,2})/(\d{4})')
    
    # 原始字符串
    text = "Meeting on 12/25/2022. Deadline is 3/8/2023."
    
    # 使用捕获组进行替换
    result = pattern.sub(r'\3-\1-\2', text)
    
    # 打印结果
    print(f"原始:{text}")
    print(f"修改后:{result}")
  2. 尝试使用反向引用(\1\2)在替换中引用捕获组。

9.常见模式

  1. 使用 \d+ 匹配一个或多个数字。

  2. 使用 ? 匹配可选字符(如 colou?r 匹配 color 或 colour)。

  3. 使用 \s+ 匹配空白字符。

10.不区分大小写

使用 re.IGNORECASE 标志启用不区分大小写的匹配。

11.注释

使用 (?#comment) 在正则表达式中添加注释,提高可读性。

12.验证

  1. 使用健壮的正则表达式模式验证电子邮件地址。

    import re
    
    def validate_email(email):
        # 电子邮件验证的正则表达式模式
        pattern = re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
        return bool(pattern.match(email))
    
    # 测试用例
    emails = [
        "user@example.com",          # 有效的电子邮件
        "user.name@company.co.uk",   # 带国家代码的有效电子邮件
        "invalid_email@no_tld",      # 无效的电子邮件(无顶级域名)
        "@missing_username.com",     # 无效的电子邮件(无用户名)
        "user@invalid_domain",       # 无效的电子邮件(域名无效)
        "user@@double_at.com",       # 无效的电子邮件(含两个@)
        "user@excessive_length_domain." + "a" * 255# 无效的电子邮件(域名过长)
    ]
    
    # 验证每个电子邮件并打印结果
    for email in emails:
        result = validate_email(email)
        print(f"{email}:{'有效' if result else '无效'}")
  • ^[a-zA-Z0-9._%+-]+:匹配用户名部分中一个或多个允许的字符。

  • @:匹配 @ 符号。

  • [a-zA-Z0-9.-]+:匹配域名部分中一个或多个允许的字符。

  • \.:匹配顶级域名前的点(.)。

  • [a-zA-Z]{2,}$:匹配两个或多个字母的顶级域名。

  • 为电话号码创建正则表达式模式。

    import re
    
    def validate_phone_number(phone_number):
        # 带或不带连字符的美国电话号码的正则表达式模式
        pattern = re.compile(r'^\+?1?\s*[-.]?\s*\(?\d{3}\)?[-.]?\s*\d{3}[-.]?\s*\d{4}$')
        return bool(pattern.match(phone_number))
    
    # 测试用例
    phone_numbers = [
        "+1 123-456-7890",     # 带国家代码的有效电话号码
        "123.456.7890",        # 带点的有效电话号码
        "(123) 456-7890",      # 带括号的有效电话号码
        "1234567890",          # 无连字符的有效电话号码
        "987-654-3210",        # 无国家代码的有效电话号码
        "invalid_phone_number"# 无效的电话号码
    ]
    
    # 验证每个电话号码并打印结果
    for phone_number in phone_numbers:
        result = validate_phone_number(phone_number)
        print(f"{phone_number}:{'有效' if result else '无效'}")
    • ^:断言字符串的开头。

    • \+?1?:匹配可选的 + 和可选的 1(国家代码)。

    • \s*[-.]?\s*:匹配可选的空格和可选的连字符或点。

    • \(?\d{3}\)?:匹配可选的左括号、三个数字和可选的右括号。

    • [-.]?\s*\d{3}[-.]?\s*\d{4}$:匹配可选的连字符或点、可选的空格、三个数字、可选的连字符或点、可选的空格,以及结尾的四个数字。

  • 为邮政编码创建正则表达式模式。

    import re
    
    def validate_zip_code(zip_code):
        # 美国邮政编码的正则表达式模式(5位或9位)
        pattern = re.compile(r'^\d{5}(?:[-\s]\d{4})?$')
        return bool(pattern.match(zip_code))
    
    # 测试用例
    zip_codes = [
        "12345",            # 有效的5位邮政编码
        "98765-4321",       # 带连字符的有效的9位邮政编码
        "56789 1234",       # 带空格的有效的9位邮政编码
        "invalid_zip_code"# 无效的邮政编码
    ]
    
    # 验证每个邮政编码并打印结果
    for zip_code in zip_codes:
        result = validate_zip_code(zip_code)
        print(f"{zip_code}:{'有效' if result else '无效'}")
    • ^:断言字符串的开头。

    • \d{5}:匹配5位数字(5位邮政编码)。

    • (?:[-\s]\d{4})?:使用非捕获组使最后四位数字可选,允许带可选连字符或空格的9位邮政编码格式。

    • $:断言字符串的结尾。

    13.转义用户输入

    将用户输入纳入正则表达式时,务必转义用户输入,以防止注入攻击。

    import re
    
    def search_string_in_text(user_input, text):
        # 在正则表达式中使用用户输入前安全转义
        escaped_user_input = re.escape(user_input)
    
        # 在正则表达式模式中使用转义后的用户输入
        pattern = re.compile(f'\\b{escaped_user_input}\\b', re.IGNORECASE)
    
        # 在文本中搜索转义后的用户输入
        match = pattern.search(text)
    
        # 打印结果
        if match:
            print(f"找到:'{user_input}' 在 '{text}' 中")
        else:
            print(f"未找到:'{user_input}' 在 '{text}' 中")
    
    # 用用户输入和文本测试
    search_string_in_text(".*", "这是一段简单的文本。")
    • re.escape(user_input)re.escape() 函数转义用户输入中的特殊字符,确保它们被视为字面字符而非正则表达式语法的一部分。

    • \\b{escaped_user_input}\\b{escaped_user_input} 被纳入正则表达式模式,前后包围 \b 单词边界以匹配确切的单词。

    • re.IGNORECASEre.IGNORECASE 标志用于执行不区分大小写的搜索。

    14.命名组

    使用命名组((?P<name>...))提高可读性,并通过名称引用捕获的组。

    15.详细模式

    启用详细模式(re.VERBOSE 或 re.X),允许模式中包含空格和注释,提高可读性。

    16.非捕获组

    使用非捕获组 (?:...) 进行分组,而不创建捕获组。

    17.Unicode 字符

    考虑使用 \p{L} 匹配任何 Unicode 字母。

    18.转义点号

    若需匹配字面点号,使用 \.

    19.验证 URL

    创建正则表达式模式验证 URL。

    import re
    
    def validate_url(url):
        # 验证 URL 的正则表达式模式
        pattern = re.compile(
            r'^(https?|ftp):\/\/'# 协议(http、https、ftp)
            r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|[0-9]{1,3}\.?|[A-Z0-9-]+\.?)'# 域名
            r'(?:\/[^\s]*)?$'# 路径
            , re.IGNORECASE
        )
        return bool(pattern.match(url))
    
    # 测试用例
    urls = [
        "http://www.example.com",
        "https://example.com/path",
        "ftp://ftp.example.net/file.txt",
        "invalid-url",
        "ftp://invalid_domain",
        "https://example_with_underscores.com"
    ]
    
    # 验证每个 URL 并打印结果
    for url in urls:
        result = validate_url(url)
        print(f"{url}:{'有效' if result else '无效'}")
    • ^(https?|ftp):\/\/:匹配协议(http、https 或 ftp)。

    • (?: ... | ... ):域名选项的非捕获组。

    • (?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?:匹配典型域名(example.com),带可选子域名。

    • |[0-9]{1,3}\.?:或者,匹配 IP 地址(带可选尾点)。

    • |[A-Z0-9-]+\.?:或者,匹配仅含字母数字的域名(example-with-hyphens.com),带可选尾点。

    • (?:\/[^\s]*)?$:匹配字符串末尾的路径(例如,/path/to/resource)。

    • re.IGNORECASEre.IGNORECASE 标志用于执行不区分大小写的匹配。

    20.提取信息

    使用捕获组从字符串中提取特定信息。

    import re
    
    def extract_email_info(email):
        # 带捕获组的正则表达式模式,用于提取电子邮件信息
        pattern = re.compile(r'^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$')
    
        # 用模式匹配电子邮件
        match = pattern.match(email)
    
        # 使用捕获组提取信息
        if match:
            username, domain, tld = match.groups()
            print(f"电子邮件:{email}")
            print(f"用户名:{username}")
            print(f"域名:{domain}")
            print(f"顶级域名:{tld}")
        else:
            print(f"无效的电子邮件格式:{email}")
    
    # 测试用例
    emails = [
        "user@example.com",
        "john.doe@company.co.uk",
        "invalid_email@no_tld",
        "@missing_username.com",
        "user@invalid_domain",
        "user@@double_at.com",
        "user@excessive_length_domain." + "a" * 255
    ]
    
    # 从每个电子邮件提取信息并打印结果
    for email in emails:
        extract_email_info(email)
        print("-" * 30)
    • ^([a-zA-Z0-9._%+-]+):电子邮件用户名部分的捕获组。

    • @:匹配 @ 符号。

    • ([a-zA-Z0-9.-]+):电子邮件域名部分的捕获组。

    • \.:匹配顶级域名前的点(.)。

    • ([a-zA-Z]{2,})$:顶级域名的捕获组。

    • match.groups():以元组形式检索捕获的组。

    21.字符集和范围

    使用字符集和范围简洁地匹配多个字符。

    import re
    
    def match_date_formats(date_string):
        # 带字符集和范围的正则表达式模式,用于匹配日期格式
        pattern = re.compile(r'^\d{1,2}[/\-]\d{1,2}[/\-]\d{2,4}$')
    
        # 检查日期字符串是否匹配模式
        if pattern.match(date_string):
            print(f"{date_string} 是有效的日期格式。")
        else:
            print(f"{date_string} 不是有效的日期格式。")
    
    # 测试用例
    date_strings = [
        "12/25/2022",
        "3-8-2023",
        "invalid_date",
        "2023-12-31",
        "15/07/2021",
        "22-10-21"
    ]
    
    # 每个日期字符串与模式匹配并打印结果
    for date_str in date_strings:
        match_date_formats(date_str)

    ^\d{1,2}[/\-]\d{1,2}[/\-]\d{2,4}$:此正则表达式模式使用字符集和范围匹配不同的日期格式。

    • ^\d{1,2}:匹配开头的1或2位数字。

    • [/\-]:匹配斜杠(/)或连字符(-)。

    • \d{1,2}:匹配1或2位数字(月份)。

    • [/\-]:匹配另一个斜杠(/)或连字符(-)。

    • \d{2,4}$:匹配结尾的2、3或4位数字(年份)。

    22.非贪婪字符匹配

    组合 .*? 用于非贪婪匹配任何字符。

    23.匹配整个单词

    使用 \b 匹配整个单词。

    24.匹配特殊字符

    要匹配字面意义上的 +* 和 ? 等特殊字符,需要转义它们。

    25.组上的量词

    将量词应用于组以匹配重复模式(例如,(ab)+)。

    26.匹配日期

    创建正则表达式模式匹配日期格式。

    1. 模式1:MM/DD/YYYY 或 MM-DD-YYYY

      import re
      
      def match_date_format_1(date_string):
          pattern = re.compile(r'^(0[1-9]|1[0-2])[/\-](0[1-9]|[12][0-9]|3[01])[/\-]\d{4}$')
          if pattern.match(date_string):
              print(f"{date_string} 匹配模式。")
          else:
              print(f"{date_string} 不匹配模式。")
      
      # 测试用例
      dates_pattern_1 = ["12/25/2022", "03-08-2023", "15/07/2021", "2023-12-31", "invalid_date"]
      for date_str in dates_pattern_1:
          match_date_format_1(date_str)

      ^(0[1-9]|1[0-2])[/\-](0[1-9]|[12][0-9]|3[01])[/\-]\d{4}$
      匹配两位数字的月份、两位数字的日期和四位数字的年份,以斜杠(/)或连字符(-)分隔。

    2. 模式2:YYYY/MM/DD 或 YYYY-MM-DD

      import re
      
      def match_date_format_2(date_string):
          pattern = re.compile(r'^\d{4}[/\-](0[1-9]|1[0-2])[/\-](0[1-9]|[12][0-9]|3[01])$')
          if pattern.match(date_string):
              print(f"{date_string} 匹配模式。")
          else:
              print(f"{date_string} 不匹配模式。")
      
      # 测试用例
      dates_pattern_2 = ["2022/12/25", "2023-03-08", "2021/15/07", "2023-12-31", "invalid_date"]
      for date_str in dates_pattern_2:
          match_date_format_2(date_str)

      ^\d{4}[/\-](0[1-9]|1[0-2])[/\-](0[1-9]|[12][0-9]|3[01])$
      匹配四位数字的年份、两位数字的月份和两位数字的日期,以斜杠(/)或连字符(-)分隔。

    3. 模式3:DD Month YYYY

      import re
      
      def match_date_format_3(date_string):
          pattern = re.compile(r'^(0[1-9]|[12][0-9]|3[01])\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+\d{4}$', re.IGNORECASE)
          if pattern.match(date_string):
              print(f"{date_string} 匹配模式。")
          else:
              print(f"{date_string} 不匹配模式。")
      
      # 测试用例
      dates_pattern_3 = ["25 Dec 2022", "08 March 2023", "15/07/2021", "31 October 2023", "invalid_date"]
      for date_str in dates_pattern_3:
          match_date_format_3(date_str)

      ^(0[1-9]|[12][0-9]|3[01])\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+\d{4}$
      匹配两位数字的日期、三位字母的月份缩写和四位数字的年份,以空格分隔。

    27.匹配 HTML 标签

    使用正则表达式匹配或提取 HTML 标签中的内容。

    import re
    
    def extract_content_from_html(html):
        # 匹配 HTML 标签内内容的正则表达式模式
        pattern = re.compile(r'<[^>]*>([^<]+)<[^>]*>')
    
        # 在 HTML 中查找所有匹配项
        matches = pattern.findall(html)
    
        # 打印提取的内容
        for match in matches:
            print(f"提取的内容:{match.strip()}")
    
    # HTML 字符串
    html_content = """
    <html>
      <body>
        <h1>Title</h1>
        <p>This is a <strong>sample</strong> paragraph.</p>
        <div class="content">Some <em>italicized</em> text.</div>
      </body>
    </html>
    """
    
    # 从 HTML 标签提取内容
    extract_content_from_html(html_content)
    • <[^>]*>:匹配开头 HTML 标签(<),后跟零个或多个非 > 字符([^>]*),以及结尾 HTML 标签(>)。

    • ([^<]+):用于匹配和提取 HTML 标签内内容的捕获组。它匹配一个或多个非 < 字符。

    • <[^>]*>:匹配结尾 HTML 标签。

    • findall:在 HTML 字符串中查找模式的所有出现。

    28.密码验证

    设计正则表达式模式验证密码强度。

    import re
    
    def validate_password_strength(password):
        # 验证强密码的正则表达式模式
        pattern = re.compile(
            r'^(?=.*[a-z])'     # 至少一个小写字母
            r'(?=.*[A-Z])'      # 至少一个大写字母
            r'(?=.*\d)'         # 至少一个数字
            r'(?=.*[@$!%*?&])'# 至少一个特殊字符
            r'(?=^[^\s]{8,}$)'# 最小长度为8个字符,不允许空格
        )
    
        if pattern.match(password):
            print(f"{password} 是强密码。")
        else:
            print(f"{password} 不符合密码强度标准。")
    
    # 测试用例
    passwords = [
        "StrongPass123!",
        "WeakPassword",
        "NoSpecialCharacter1",
        "Short!23",
        "NoUpperLowerCase@1"
    ]
    
    # 验证每个密码并打印结果
    for password in passwords:
        validate_password_strength(password)
    • (?=.*[a-z]):至少一个小写字母。

    • (?=.*[A-Z]):至少一个大写字母。

    • (?=.*\d):至少一个数字。

    • (?=.*[@$!%*?&]):至少一个特殊字符(可自定义这个集合)。

    • (?=^[^\s]{8,}$):最小长度为8个字符,且不允许空格。

    29.替换空白字符

    用单个空格(\s+)替换连续的空白字符。

    30.提取数字

    使用 \d+ 从字符串中提取数字。

    31.提取 URL

    创建正则表达式模式从文本中提取 URL。

    1. 模式1:基本 URL 提取

      import re
      
      def extract_urls(text):
          # 提取 URL 的正则表达式模式
          pattern = re.compile(r'https?://\S+|www\.\S+')
      
          # 在文本中查找所有匹配项
          matches = pattern.findall(text)
      
          # 打印提取的 URL
          for match in matches:
              print(f"提取的 URL:{match}")
      
      # 测试用例
      text_with_urls = """
      Check out this website: https://www.example.com.
      For more information, visit http://www.another-example.org.
      """
      
      # 从文本中提取 URL
      extract_urls(text_with_urls)
    • https?:匹配 "http" 或 "https"。

    • ://:匹配 "://"。

    • \S+:匹配一个或多个非空白字符(域名)。

    • |:或运算符。

    • www\.\S+:匹配 "www." 后跟一个或多个非空白字符。

  • 模式2:扩展 URL 提取

    import re
    
    def extract_urls_extended(text):
        # 提取带可选 www 和查询参数的 URL 的正则表达式模式
        pattern = re.compile(r'https?://(?:www\.)?\S+(?:\?\S+)?')
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(text)
    
        # 打印提取的 URL
        for match in matches:
            print(f"提取的 URL:{match}")
    
    # 测试用例
    text_with_urls_extended = """
    Check out this website: https://www.example.com/path/page?query=123.
    For more information, visit http://another-example.org.
    """
    
    # 从文本中提取 URL
    extract_urls_extended(text_with_urls_extended)
    • (?:www\.)?:可选 "www." 的非捕获组。

    • (?:\?\S+)?):可选查询参数(以 "?" 开头)的非捕获组。

    32.匹配 HTML 实体

    使用正则表达式匹配或替换 HTML 实体。

    import re
    from html import unescape
    
    def replace_html_entities(text):
        # 匹配 HTML 实体的正则表达式模式
        pattern = re.compile(r'&[a-zA-Z]+;')
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(text)
    
        # 将每个 HTML 实体替换为其解码后的等效字符
        for match in matches:
            decoded_entity = unescape(match)
            text = text.replace(match, decoded_entity)
    
        return text
    
    # 测试用例
    html_text = "This is an example with <b>HTML</b> entities."
    
    # 替换文本中的 HTML 实体
    result_text = replace_html_entities(html_text)
    
    # 打印结果
    print("原始文本:", html_text)
    print("替换后:", result_text)

    正则表达式模式 &[a-zA-Z]+; 用于匹配常见的 HTML 实体。然后使用 html 模块中的 unescape 函数将每个 HTML 实体替换为其解码后的等效字符。

    33.匹配文件路径

    设计正则表达式模式匹配文件路径。

    1. 模式1:Unix/Linux 文件路径

      import re
      
      def match_unix_file_path(path):
          # 匹配 Unix/Linux 文件路径的正则表达式模式
          pattern = re.compile(r'^\/(?:[^\/]+\/)*[^\/]+$')
      
          if pattern.match(path):
              print(f"{path} 是有效的 Unix/Linux 文件路径。")
          else:
              print(f"{path} 不是有效的 Unix/Linux 文件路径。")
      
      # 测试用例
      unix_paths = [
          "/home/user/documents/file.txt",
          "/var/www/html/index.html",
          "relative/path/to/file",
          "invalid\\path\\file.txt"
      ]
      
      for path in unix_paths:
          match_unix_file_path(path)
    • ^:断言字符串的开头。

    • \/:匹配根目录("/")。

    • (?:[^\/]+\/)*:非捕获组,匹配零个或多个非斜杠字符后跟斜杠的序列。

    • [^\/]+$:匹配字符串末尾一个或多个非斜杠字符。

  • 模式2:Windows 文件路径

    import re
    
    def match_windows_file_path(path):
        # 匹配 Windows 文件路径的正则表达式模式
        pattern = re.compile(r'^[a-zA-Z]:\\(?:[^\\]+\\)*[^\\]+$')
    
        if pattern.match(path):
            print(f"{path} 是有效的 Windows 文件路径。")
        else:
            print(f"{path} 不是有效的 Windows 文件路径。")
    
    # 测试用例
    windows_paths = [
        "C:\\Users\\User\\Documents\\file.txt",
        "D:/Projects/project1/code.py",
        "\\absolute\\path\\file.txt",
        "/unix/style/path/file"
    ]
    
    for path in windows_paths:
        match_windows_file_path(path)
    • ^:断言字符串的开头。

    • [a-zA-Z]:\\:匹配驱动器号(例如,"C:")后跟反斜杠。

    • (?:[^\\]+\\)*:非捕获组,匹配零个或多个非反斜杠字符后跟反斜杠的序列。

    • [^\\]+$:匹配字符串末尾一个或多个非反斜杠字符。

    34.提取电子邮件地址

    创建正则表达式模式从文本中提取电子邮件地址。

    1. 模式1:基本电子邮件地址提取

      import re
      
      def extract_email_addresses(text):
          # 基本电子邮件地址提取的正则表达式模式
          pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b')
      
          # 在文本中查找所有匹配项
          matches = pattern.findall(text)
      
          # 打印提取的电子邮件地址
          for match in matches:
              print(f"提取的电子邮件:{match}")
      
      # 测试用例
      text_with_emails = """
      Contact us at support@example.com for assistance.
      Send your inquiries to info@company.org or sales@business.com.
      Invalid emails: user@invalid, @missing_username.com, email@in@valid.com
      """
      
      # 从文本中提取电子邮件地址
      extract_email_addresses(text_with_emails)

      \b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b

    • \b:单词边界,确保匹配整个电子邮件地址。

    • [A-Za-z0-9._%+-]+:匹配电子邮件的用户名部分。

    • @:匹配 @ 符号。

    • [A-Za-z0-9.-]+:匹配域名。

    • \.:匹配顶级域名前的点。

    • [A-Z|a-z]{2,}:匹配至少2个字符的顶级域名(TLD)。

  • 模式2:扩展电子邮件地址提取

    import re
    
    def extract_email_addresses_extended(text):
        # 扩展电子邮件地址提取的正则表达式模式
        pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}(?:\.[A-Z|a-z]{2,})?\b')
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(text)
    
        # 打印提取的电子邮件地址
        for match in matches:
            print(f"提取的电子邮件:{match}")
    
    # 测试用例
    text_with_emails_extended = """
    Contact us at support@example.com for assistance.
    Send your inquiries to info@company.org or sales@business.co.uk.
    Invalid emails: user@invalid, @missing_username.com, email@in@valid.com
    """
    
    # 从文本中提取电子邮件地址
    extract_email_addresses_extended(text_with_emails_extended)

    ...(?:\.[A-Z|a-z]{2,})?\b

    • (?: ... )?:可选附加子域名的非捕获组。

    • \.:匹配附加子域名前的点。

    • [A-Z|a-z]{2,}:匹配至少2个字符的附加子域名。

    35.匹配 IPv4 地址

    设计正则表达式模式匹配 IPv4 地址。

    1. 模式1:基本 IPv4 地址匹配

      import re
      
      def match_ipv4_addresses(text):
          # 基本 IPv4 地址匹配的正则表达式模式
          pattern = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b')
      
          # 在文本中查找所有匹配项
          matches = pattern.findall(text)
      
          # 打印匹配的 IPv4 地址
          for match in matches:
              print(f"匹配的 IPv4 地址:{match}")
      
      # 测试用例
      text_with_ipv4 = """
      Server 1: 192.168.1.1
      Server 2: 10.0.0.255
      Invalid IP: 256.256.256.256
      """
      
      # 在文本中匹配 IPv4 地址
      match_ipv4_addresses(text_with_ipv4)

      \b(?:\d{1,3}\.){3}\d{1,3}\b

    • \b:单词边界,确保匹配整个 IPv4 地址。

    • (?:\d{1,3}\.){3}:非捕获组,匹配三次 "1-3 位数字后跟点"。

    • \d{1,3}:匹配最后一个八位字节(1-3 位数字)。

  • 模式2:扩展 IPv4 地址匹配

    import re
    
    def match_ipv4_addresses_extended(text):
        # 扩展 IPv4 地址匹配的正则表达式模式
        pattern = re.compile(r'\b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
                           r'(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}\b')
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(text)
    
        # 打印匹配的 IPv4 地址
        for match in matches:
            print(f"匹配的 IPv4 地址:{match}")
    
    # 测试用例
    text_with_ipv4_extended = """
    Server 1: 192.168.1.1
    Server 2: 10.0.0.255
    Invalid IP: 256.256.256.256
    """
    
    # 在文本中匹配 IPv4 地址
    match_ipv4_addresses_extended(text_with_ipv4_extended)

    \b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

    • (?: ... ){3}:非捕获组,匹配三次以下模式。

    • 25[0-5]:匹配 250 到 255 之间的数字。

    • 2[0-4][0-9]:匹配 200 到 249 之间的数字。

    • [01]?[0-9][0-9]?:匹配 0 到 199 之间的数字。

    36.转义符上的量词

    将量词直接应用于转义符(例如,\d{3} 匹配三位数字)。

    37.匹配信用卡号

    创建正则表达式模式匹配或验证信用卡号。

    1. 模式1:基本信用卡号验证

      import re
      
      def validate_credit_card_number_basic(card_number):
          # 基本信用卡号验证的正则表达式模式
          pattern = re.compile(r'^\d{13,19}$')
      
          if pattern.match(card_number):
              print(f"{card_number} 可能是有效的信用卡号。")
          else:
              print(f"{card_number} 不是有效的信用卡号。")
      
      # 测试用例
      credit_cards_basic = [
          "1234567890123",
          "4567-8901-2345-6789",
          "1234 5678 9012 3456",
          "invalid_card",
      ]
      
      for card in credit_cards_basic:
          validate_credit_card_number_basic(card)

      ^\d{13,19}$:匹配长度在13到19个字符之间的数字字符串。

    2. 模式2:带卢恩算法的信用卡号验证

      import re
      
      def validate_credit_card_number_luhn(card_number):
          # 带卢恩算法的信用卡号验证的正则表达式模式
          pattern = re.compile(r'^\d{13,19}$')
      
          ifnot pattern.match(card_number):
              print(f"{card_number} 不是有效的信用卡号。")
              return
      
          # 移除非数字字符
          digits = [int(digit) for digit in card_number if digit.isdigit()]
      
          # 应用卢恩算法
          total = sum(digits[::-2] + [sum(divmod(d * 2, 10)) for d in digits[-2::-2]])
          if total % 10 == 0:
              print(f"{card_number} 是有效的信用卡号。")
          else:
              print(f"{card_number} 不是有效的信用卡号。")
      
      # 测试用例
      credit_cards_luhn = [
          "1234567890123",
          "4567-8901-2345-6789",
          "1234 5678 9012 3456",
          "invalid_card",
      ]
      
      for card in credit_cards_luhn:
          validate_credit_card_number_luhn(card)
    • ^\d{13,19}$:与基本模式相同,用于初始数字验证。

    • 卢恩算法用于检查信用卡号的有效性。

    38.匹配特定单词

    使用 \b 匹配较大文本中的特定单词。

    39.转义字符

    1. 使用 \ 转义特殊字符,如 ^$()[]{}.*+?|\

    2. 在非特殊字符前使用 \ 以字面匹配它。

    40.Unicode 和单词边界

    1. 使用 \b 作为单词边界,\B 作为非单词边界。

    2. 对于 Unicode 单词边界,结合 re.UNICODE 标志使用 \b

    41.匹配或排除字符

    1. 使用 . 匹配除换行符外的任何字符。

    2. 使用 [^...] 匹配不在指定集合中的任何字符。

    42.量词组合

    1. 组合量词以提高灵活性(例如,a{2,4} 匹配 'aa'、'aaa' 或 'aaaa')。

    2. 使用 {0,} 或 * 表示零次或多次出现。

    43.分组和选择

    1. 使用括号进行分组,并对序列应用量词。

      import re
      
      # 包含电话号码的示例文本
      text = """
      Phone Numbers:
      - (555) 123-4567
      - (123) 456-7890
      - (987) 654-3210
      """
      
      # 带分组和量词的正则表达式模式,用于匹配电话号码
      pattern = re.compile(r'\(\d{3}\) \d{3}-\d{4}')
      
      # 在文本中查找所有匹配项
      matches = pattern.findall(text)
      
      # 打印匹配的电话号码
      for match in matches:
          print("匹配的电话号码:", match)
    • \(:匹配左括号。

    • \d{3}:匹配恰好三位数字。

    • \):匹配右括号。

    • :匹配空格。

    • \d{3}:匹配恰好三位数字。

    • -:匹配连字符。

    • \d{4}:匹配恰好四位数字。

  • 利用 (?:...) 作为非捕获组。

  • 利用选择匹配多个可能的模式(例如,cat|dog|bird)。

  • 44.替换中的捕获组

    1. 在替换模式中使用 \1\2 等利用捕获组。

    2. 对命名捕获组使用 \g<name>

    45.环视

    1. 使用正向后顾((?<=...))匹配前面有特定模式的内容。

    2. 应用负向后顾((?<!...))匹配前面没有特定模式的内容。

    3. 利用正向前瞻((?=...))匹配后面有特定模式的内容。

    4. 利用负向前瞻((?!...))匹配后面没有特定模式的内容。

    46.命名捕获组

    1. 使用命名捕获组提高代码可读性。

    2. 使用 match.group('name') 访问命名捕获组。

    47.详细模式

    1. 启用详细模式(re.VERBOSE 或 re.X),支持多行模式和注释。

    2. 将复杂模式拆分为多行,提高可读性。

      import re
      
      # 包含电子邮件地址的示例文本
      text = """
      Email Addresses:
      - user@example.com
      - john.doe@company.org
      - contact@my-website.co.uk
      """
      
      # 带换行符的正则表达式模式,提高可读性
      pattern = re.compile(
          r'\b'                    # 单词边界
          r'[a-zA-Z0-9._%+-]+@'    # 用户名部分
          r'[a-zA-Z0-9.-]+\.'      # 域名部分(第一级)
          r'[A-Z|a-z]{2,}'         # 域名部分(顶级)
          r'\b'                    # 单词边界
      )
      
      # 在文本中查找所有匹配项
      matches = pattern.findall(text)
      
      # 打印匹配的电子邮件地址
      for match in matches:
          print("匹配的电子邮件地址:", match)

    48.标志和模式

    1. 利用标志,如 re.IGNORECASE 进行不区分大小写的匹配。

    2. 使用按位 OR 组合多个标志(例如,re.IGNORECASE | re.MULTILINE)。

    49.验证和提取电子邮件域名

    1. 使用正则表达式模式验证电子邮件域名。

      import re
      
      def validate_email_domain(email):
          # 基本电子邮件地址验证的正则表达式模式
          email_pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b')
      
          # 检查电子邮件地址是否匹配模式
          ifnot email_pattern.match(email):
              print(f"{email} 不是有效的电子邮件地址。")
              return
      
          # 从电子邮件地址提取域名
          domain_pattern = re.compile(r'@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b')
          domain_match = domain_pattern.search(email)
      
          if domain_match:
              domain = domain_match.group()[1:]
              print(f"{email} 的域名是 {domain}。")
          else:
              print(f"无法从 {email} 提取域名。")
      
      # 测试用例
      emails = [
          "user@example.com",
          "john.doe@company.org",
          "invalid-email",
      ]
      
      for email in emails:
          validate_email_domain(email)

      请注意,这种方法有局限性,不能保证域名的有效性。对于更可靠的解决方案,考虑使用专门的电子邮件验证库或服务。使用 DNS 查找验证域名是更可靠的方法,但需要正则表达式之外的额外步骤。

    • email_pattern 正则表达式与基本电子邮件地址验证中使用的相同。

    • domain_pattern 正则表达式用于从电子邮件地址提取域名部分。

    • @[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b:匹配 @ 符号后的域名部分。

  • 使用模式中的捕获组提取电子邮件域名。

    import re
    
    def extract_email_domain(email):
        # 带捕获组的正则表达式模式,用于提取电子邮件域名
        pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@([A-Za-z0-9.-]+\.[A-Z|a-z]{2,})\b')
    
        # 用模式匹配电子邮件地址
        match = pattern.search(email)
    
        if match:
            domain = match.group(1)
            print(f"{email} 的域名是 {domain}。")
        else:
            print(f"无法从 {email} 提取域名。")
    
    # 测试用例
    emails = [
        "user@example.com",
        "john.doe@company.org",
        "invalid-email",
    ]
    
    for email in emails:
        extract_email_domain(email)

    \b[A-Za-z0-9._%+-]+@([A-Za-z0-9.-]+\.[A-Z|a-z]{2,})\b

    group(1) 方法用于提取第一个(也是唯一一个)捕获组捕获的内容,即电子邮件域名。

    • \b:单词边界,确保匹配整个电子邮件地址。

    • [A-Za-z0-9._%+-]+:匹配电子邮件的用户名部分。

    • @:匹配 @ 符号。

    • ([A-Za-z0-9.-]+\.[A-Z|a-z]{2,}):域名部分的捕获组。

    • \b:单词边界,确保匹配整个电子邮件地址。

    50.匹配平衡括号

    创建正则表达式匹配带平衡括号的表达式。

    import regex
    
    def is_balanced(expression):
        # 匹配带平衡括号的表达式的正则表达式模式
        pattern = regex.compile(r'''
            \(
                (?: [^()]+ | (?R) )*
            \)
        ''', regex.VERBOSE)
    
        return bool(pattern.fullmatch(expression))
    
    # 测试用例
    expressions = [
        "(a + b) * (c - d)",
        "((x + y) * z)",
        "((a + b) * (c - d)",
        "a + b) * (c - d)",
    ]
    
    for expr in expressions:
        if is_balanced(expr):
            print(f"表达式 '{expr}' 有平衡的括号。")
        else:
            print(f"表达式 '{expr}' 没有平衡的括号。")
    • \(:匹配左括号。

    • (?: [^()]+ | (?R) )*:非捕获组,零次或多次出现以下内容:

      • [^()]+:除括号外的任何字符序列。

      • (?R):递归匹配整个模式。

    • \):匹配右括号。

    Python 中的 regex 模块支持递归模式,允许定义引用自身的模式。在这种情况下,模式 (?R) 用于递归匹配整个模式。

    51.验证 IP 地址

    1. 设计正则表达式模式验证 IPv4 和 IPv6 地址。

      import re
      
      def validate_ipv4_address(ipv4):
          # IPv4 地址验证的正则表达式模式
          pattern = re.compile(
              r'^'
              r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
              r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
              r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
              r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
          )
      
          return bool(pattern.match(ipv4))
      
      # 测试用例
      ipv4_addresses = [
          "192.168.1.1",
          "10.0.0.255",
          "256.256.256.256",
          "invalid-ip",
      ]
      
      for ipv4 in ipv4_addresses:
          if validate_ipv4_address(ipv4):
              print(f"{ipv4} 是有效的 IPv4 地址。")
          else:
              print(f"{ipv4} 不是有效的 IPv4 地址。")
      import re
      
      def validate_ipv6_address(ipv6):
          # IPv6 地址验证的正则表达式模式
          pattern = re.compile(
              r'^'
              r'(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$'
          )
      
          return bool(pattern.match(ipv6))
      
      # 测试用例
      ipv6_addresses = [
          "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
          "invalid-ipv6",
      ]
      
      for ipv6 in ipv6_addresses:
          if validate_ipv6_address(ipv6):
              print(f"{ipv6} 是有效的 IPv6 地址。")
          else:
              print(f"{ipv6} 不是有效的 IPv6 地址。")

      IPv4 地址验证:

      IPv6 地址验证:

    • (?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}:验证 IPv6 地址块。

    • ::匹配冒号分隔符。

    • ^:断言字符串的开头。

    • (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):验证每个八位字节。

    • \.:匹配点分隔符。

    • $:断言字符串的结尾。

  • 使用该模式从文本中提取 IP 地址。

    import re
    
    def extract_ip_addresses(text):
        # IPv4 地址提取的正则表达式模式
        ipv4_pattern = re.compile(r'\b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b')
    
        # IPv6 地址提取的正则表达式模式
        ipv6_pattern = re.compile(r'\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b')
    
        # 在文本中查找所有匹配项
        ipv4_matches = ipv4_pattern.findall(text)
        ipv6_matches = ipv6_pattern.findall(text)
    
        # 打印匹配的 IP 地址
        print("IPv4 地址:")
        for ipv4_match in ipv4_matches:
            print(ipv4_match)
    
        print("\nIPv6 地址:")
        for ipv6_match in ipv6_matches:
            print(ipv6_match)
    
    # 测试用例
    sample_text = """
    本文中的 IP 地址:
    - IPv4:192.168.1.1、10.0.0.255、256.256.256.256
    - IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334
    """
    
    extract_ip_addresses(sample_text)
  • 52.匹配 Markdown 链接

    创建正则表达式模式匹配和提取 Markdown 文本中的链接。

    import re
    
    def extract_markdown_links(markdown_text):
        # 提取行内链接的正则表达式模式
        inline_link_pattern = re.compile(r'\[([^\]]+)\]\(([^)]+)\)')
    
        # 提取引用式链接的正则表达式模式
        reference_link_pattern = re.compile(r'\[([^\]]+)\]:\s*([^\s]+)')
    
        # 在文本中查找所有行内链接
        inline_links = inline_link_pattern.findall(markdown_text)
    
        # 在文本中查找所有引用式链接
        reference_links = reference_link_pattern.findall(markdown_text)
    
        # 打印提取的链接
        print("行内链接:")
        for title, url in inline_links:
            print(f"标题:{title},URL:{url}")
    
        print("\n引用式链接:")
        for title, url in reference_links:
            print(f"标题:{title},URL:{url}")
    
    # 测试用例
    sample_markdown = """
    Here are some links in Markdown:
    
    - [Google](https://www.google.com)
    - [OpenAI](https://www.openai.com)
    
    Reference-style links:
    
    [Markdown Guide]: https://www.markdownguide.org
    [GitHub]: https://github.com
    """
    
    extract_markdown_links(sample_markdown)
    • inline_link_pattern 正则表达式捕获方括号([])内的文本作为链接标题,圆括号(())内的文本作为链接 URL。

    • reference_link_pattern 正则表达式捕获方括号([])内的文本作为链接标题,冒号(:)后的文本(含可选空格)作为链接 URL。

    53.匹配带引号的字符串

    设计正则表达式模式匹配文本中的带引号字符串。

    import re
    
    def extract_quoted_strings(text):
        # 提取单引号字符串的正则表达式模式
        single_quoted_pattern = re.compile(r"'([^']+)'")
    
        # 提取双引号字符串的正则表达式模式
        double_quoted_pattern = re.compile(r'"([^"]+)"')
    
        # 在文本中查找所有单引号字符串
        single_quoted_strings = single_quoted_pattern.findall(text)
    
        # 在文本中查找所有双引号字符串
        double_quoted_strings = double_quoted_pattern.findall(text)
    
        # 打印提取的带引号字符串
        print("单引号字符串:")
        for single_quoted in single_quoted_strings:
            print(single_quoted)
    
        print("\n双引号字符串:")
        for double_quoted in double_quoted_strings:
            print(double_quoted)
    
    # 测试用例
    sample_text = """
    Here are some quoted strings in the text:
    
    - Single-quoted: 'Hello, world!'
    - Double-quoted: "This is a quoted string."
    
    Mixed quotes: 'Single and "double" quotes.'
    """
    
    extract_quoted_strings(sample_text)
    • single_quoted_pattern 正则表达式捕获单引号(')内的文本作为单引号字符串的内容。

    • double_quoted_pattern 正则表达式捕获双引号(")内的文本作为双引号字符串的内容。

    54.提取 HTML 属性

    构建模式从文本中提取 HTML 标签属性。

    import re
    
    def extract_html_attributes(html_text):
        # 提取 HTML 标签属性的正则表达式模式
        pattern = re.compile(r'<\s*([a-zA-Z0-9_-]+)(?:\s+([a-zA-Z0-9_-]+)\s*=\s*(".*?"|\'.*?\'|[^\s>]+))*\s*/?>')
    
        # 在文本中查找所有 HTML 标签
        matches = pattern.finditer(html_text)
    
        # 提取并打印标签名称和属性
        for match in matches:
            tag_name = match.group(1)
            print(f"标签:{tag_name}")
    
            if match.group(2):
                attributes = match.group(2)
                attribute_pattern = re.compile(r'([a-zA-Z0-9_-]+)\s*=\s*(".*?"|\'.*?\'|[^\s>]+)')
    
                # 提取并打印单个属性
                for attribute_match in attribute_pattern.finditer(attributes):
                    attribute_name = attribute_match.group(1)
                    attribute_value = attribute_match.group(2)
                    print(f"  属性:{attribute_name},值:{attribute_value}")
    
    # 测试用例
    sample_html = """
    <div class="container" id='main-container' data-value=42>
        <p style="color: blue;">This is a paragraph</p>
        <a href="https://example.com" target="_blank">Visit Example</a>
    </div>
    """
    
    extract_html_attributes(sample_html)
    • pattern 正则表达式捕获标签名称及其属性。

    • attribute_pattern 正则表达式捕获单个属性及其值。

    55.组上的量词

    将量词直接应用于组(例如,(ab)+ 匹配一个或多个 'ab' 序列)。

    56.匹配十六进制颜色

    设计模式匹配 HTML 中的十六进制颜色代码。

    import re
    
    def extract_hex_color_codes(html_text):
        # 匹配十六进制颜色代码的正则表达式模式
        pattern = re.compile(r'#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})\b')
    
        # 在文本中查找所有颜色代码
        color_codes = pattern.findall(html_text)
    
        # 打印匹配的颜色代码
        print("十六进制颜色代码:")
        for color_code in color_codes:
            print(color_code)
    
    # 测试用例
    sample_html = """
    <style>
        .background-color {
            background-color: #aabbcc;
        }
        .text-color {
            color: #123;
        }
    </style>
    """
    
    extract_hex_color_codes(sample_html)

    pattern 正则表达式匹配短格式(#abc)或长格式(#aabbcc)的十六进制颜色代码。

    • (?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})

      • (?: ... ):非捕获组。

      • [0-9a-fA-F]{3}:匹配三位十六进制数字。

      • |:选择。

      • [0-9a-fA-F]{6}:匹配六位十六进制数字。

    此模式将在给定的 HTML 文本中找到所有十六进制颜色代码。请注意,此正则表达式可能还会匹配其他类似十六进制颜色代码的模式。为了更精确地提取,你可以考虑使用专门的 HTML 解析库(如 BeautifulSoup),然后从 style 属性或内联样式中提取颜色代码。

    57.验证信用卡有效期

    创建正则表达式模式验证信用卡有效期。

    import re
    from datetime import datetime
    
    def validate_credit_card_expiry(expiry_date):
        # 验证 MM/YY 或 MM/YYYY 格式的信用卡有效期的正则表达式模式
        pattern = re.compile(r'^(0[1-9]|1[0-2])/(20\d{2}|[3-9]\d)$')
    
        # 检查日期是否匹配模式
        ifnot pattern.match(expiry_date):
            returnFalse
    
        # 从日期中提取月份和年份
        month, year = map(int, expiry_date.split('/'))
    
        # 处理年份(如果是两位数)
        if year < 100:
            year += 2000
    
        # 检查日期是否在未来
        current_date = datetime.now()
        expiry_date = datetime(year, month, 1)
    
        return expiry_date > current_date
    
    # 测试用例
    expiry_dates = [
        "12/23",  # 有效
        "06/2024",  # 有效
        "13/25",  # 无效(月份超过12)
        "01/2000",  # 无效(已过期)
        "MM/YY",  # 无效(格式无效)
    ]
    
    for expiry_date in expiry_dates:
        if validate_credit_card_expiry(expiry_date):
            print(f"{expiry_date} 是有效的信用卡有效期。")
        else:
            print(f"{expiry_date} 不是有效的信用卡有效期。")

    pattern 正则表达式验证 MM/YY 或 MM/YYYY 格式的日期。

    • ^(0[1-9]|1[0-2]):匹配 MM 格式的月份(01 到 12)。

    • /:匹配分隔符。

    • (20\d{2}|[3-9]\d)$:匹配 YYYY 格式(以 20 开头)或 YY 格式(以 3-9 开头)的年份。

    • Python 代码随后检查日期是否在未来。

    请注意,虽然正则表达式可以执行基本验证,但必须基于实际日期执行额外检查以确保准确性。对于更可靠的日期处理,考虑使用 dateutil.parser 等日期解析库。

    58.匹配函数调用

    设计正则表达式模式匹配代码中的函数调用。

    import re
    
    def extract_function_calls(code_text):
        # 匹配函数调用的正则表达式模式
        pattern = re.compile(r'\b([a-zA-Z_]\w*)\s*\([^)]*\)')
    
        # 在文本中查找所有函数调用
        matches = pattern.findall(code_text)
    
        # 打印匹配的函数调用
        print("函数调用:")
        for match in matches:
            print(match)
    
    # 测试用例
    sample_code = """
    def hello_world():
        print("Hello, World!")
    
    result = add_numbers(5, 7) + multiply(3, 4)
    """
    
    extract_function_calls(sample_code)

    pattern 正则表达式捕获函数调用,包含以下组件:

    • \b:单词边界,确保匹配完整的函数名。

    • ([a-zA-Z_]\w*):捕获函数名(以字母或下划线开头,后跟字母、数字或下划线)。

    • \s*:匹配可选空格。

    • \(:匹配函数调用的左括号。

    • [^)]*:匹配除右括号外的任何字符,允许包含参数。

    • \):匹配函数调用的右括号。

    59.匹配 SQL 查询

    创建模式匹配文本中的 SQL 查询。

    import re
    
    def extract_sql_queries(text):
        # 匹配 SQL 查询的正则表达式模式
        pattern = re.compile(r'\b(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|FROM|JOIN|WHERE|ORDER BY|GROUP BY|HAVING|LIMIT|AND|OR|IN|SET|VALUES|INTO|AS|ON|INNER|LEFT|RIGHT|OUTER)\b', re.IGNORECASE)
    
        # 在文本中查找所有 SQL 关键字
        matches = pattern.findall(text)
    
        # 打印匹配的 SQL 查询
        print("SQL 关键字:")
        for match in matches:
            print(match)
    
    # 测试用例
    sample_text = """
    SELECT * FROM employees WHERE department = 'IT';
    INSERT INTO customers (name, email) VALUES ('John Doe', 'john@example.com');
    UPDATE products SET price = 29.99 WHERE category = 'Electronics';
    """
    
    extract_sql_queries(sample_text)
    • pattern 正则表达式捕获常见的 SQL 关键字,如 SELECT、INSERT、UPDATE、DELETE 等。

    • \b:单词边界,确保匹配完整的关键字。

    • re.IGNORECASE:标志用于使模式不区分大小写。

    这是一个基本示例,可能无法覆盖所有 SQL 变体。对于更复杂的场景(如处理嵌套查询或注释),可能需要更复杂的解析器。对于更准确的 SQL 解析,考虑使用专门的 SQL 解析库或工具。

    60.匹配 XML 标签

    1. 设计模式匹配并提取 XML 标签之间的内容。

    import re
    
    def extract_xml_content(xml_text, tag_name):
        # 匹配并提取 XML 标签之间内容的正则表达式模式
        pattern = re.compile(rf'<{tag_name}[^>]*>(.*?)<\/{tag_name}>', re.DOTALL)
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(xml_text)
    
        # 打印提取的内容
        print(f"<{tag_name}> 标签之间的内容:")
        for match in matches:
            print(match.strip())
    
    # 测试用例
    sample_xml = """
    <book>
        <title>Introduction to XML</title>
        <author>John Doe</author>
        <content>
            This is a sample book about XML.
        </content>
    </book>
    """
    
    extract_xml_content(sample_xml, 'title')
    extract_xml_content(sample_xml, 'content')
    • 该模式用于捕获指定 XML 标签之间的内容。

    • rf'<{tag_name}[^>]*>(.*?)<\/{tag_name}>':通过 f 字符串动态插入标签名,匹配开始标签 <tag_name> 与对应结束标签 </tag_name> 之间的内容。

    • re.DOTALL 标志使正则表达式中的 . 能匹配包括换行符在内的所有字符。

    需注意,此示例适用于无嵌套标签的简单场景。对于复杂 XML 解析,建议使用 ElementTree 或 lxml 等专用 XML 解析库,它们能更精准地处理 XML 结构。

    1. 若 XML 的开始标签包含属性,可调整模式以适配,例如用 (\w+)\s*=\s*["']([^"']*)["'] 捕获属性名和属性值。

    2. 若 XML 包含命名空间前缀,可使用适配模式(如 (\w+:)?(\w+))同时捕获命名空间前缀和本地名称。

    61.匹配句子

    创建模式匹配文本中的完整句子。

    import re
    
    def extract_sentences(text):
        # 匹配英文完整句子的正则表达式模式
        pattern = re.compile(r'(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s')
    
        # 按模式将文本拆分为句子
        sentences = re.split(pattern, text)
    
        # 打印提取的句子
        print("提取的句子:")
        for sentence in sentences:
            print(sentence.strip())
    
    # 测试用例
    sample_text = """
    This is the first sentence. It contains multiple words.
    The second sentence has more words. It also ends with a period.
    A third sentence exists as well, with a question mark at the end?
    """
    
    extract_sentences(sample_text)
    • 该模式通过正向后顾检测句子结尾的标点(. 或 ?)及后续空白。

    • (?<!\w\.\w.):负向后顾,排除 "Mr." 等缩写。

    • (?<![A-Z][a-z]\.):负向后顾,排除句尾常见缩写。

    • (?<=\.|\?):正向后顾,匹配句号或问号后跟空白的情况。

    需注意,此示例无法覆盖所有复杂文本场景。对于高级句子提取,建议使用 spaCy 或 NLTK 等自然语言处理库,它们专为处理语言结构设计。

    62.提取 HTML 注释

    设计模式提取 HTML 注释内的内容。

    import re
    
    def extract_html_comments(html_text):
        # 匹配并提取 HTML 注释内内容的正则表达式模式
        pattern = re.compile(r'<!--(.*?)-->', re.DOTALL)
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(html_text)
    
        # 打印提取的内容
        print("HTML 注释内的内容:")
        for match in matches:
            print(match.strip())
    
    # 测试用例
    sample_html = """<!DOCTYPE html><html><head>
        <title>HTML Comments Example</title></head><body>
        <!-- This is a comment -->
        <p>This is a paragraph.</p>
        <!-- Another comment
        spanning multiple lines -->
        <div>
            <p>More content</p>
        </div></body></html>
    """
    
    extract_html_comments(sample_html)
    • pattern 正则表达式使用非贪婪匹配 (.*?) 捕获 <!-- 和 --> 之间的内容。

    • re.DOTALL:标志使正则表达式中的点(.)匹配包括换行符在内的所有字符。

    需要注意的是,虽然此示例在简单场景下可行,但使用正则表达式解析 HTML 注释可能无法覆盖所有边缘情况。对于更可靠的 HTML 解析,建议使用 Python 中的 BeautifulSoup 或 lxml 等专用 HTML 解析库,这些库专为处理 HTML 结构的复杂性而设计,能提供更可靠的 HTML 文档解析方案。

    63.匹配浮点数

    创建正则表达式模式匹配浮点数。

    import re
    
    def extract_float_numbers(text):
        # 匹配浮点数的正则表达式模式
        pattern = re.compile(r'-?\b(?:\d+\.\d*|\.\d+|\d+)(?:[eE][-+]?\d+)?\b')
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(text)
    
        # 打印提取的浮点数
        print("提取的浮点数:")
        for match in matches:
            print(match)
    
    # 测试用例
    sample_text = """
    文本中的数字:3.14、-0.5、123.456、.789、1.2e3、-4.56E-7
    非数字:abc、1.2.3、1e、1E2.5
    """
    
    extract_float_numbers(sample_text)

    pattern 正则表达式捕获多种格式的浮点数,各部分含义如下:

    • -?:可选的负号,用于匹配负数。

    • \b:单词边界,确保匹配完整的数字。

    • (?:\d+\.\d*|\.\d+|\d+):用于匹配三种情况的分组:

      • \d+\.\d*:带整数部分且小数部分可选的十进制数。

      • \.\d+:以小数点开头的十进制数。

      • \d+:无小数点的整数部分。

    • (?:[eE][-+]?\d+)?:可选的指数部分,形式为 e 或 E 后跟可选符号及数字。

    64.验证 MAC 地址

    设计正则表达式模式验证 MAC 地址。

    import re
    
    def validate_mac_address(mac_address):
        # 验证 MAC 地址的正则表达式模式
        pattern = re.compile(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$')
    
        # 检查 MAC 地址是否匹配模式
        return bool(pattern.match(mac_address))
    
    # 测试用例
    mac_addresses = [
        "00:1a:2b:3c:4d:5e",
        "01-23-45-67-89-ab",
        "a1:b2:c3:d4:e5:f6",
        "invalid_mac",
    ]
    
    for mac_address in mac_addresses:
        if validate_mac_address(mac_address):
            print(f"{mac_address} 是有效的 MAC 地址。")
        else:
            print(f"{mac_address} 不是有效的 MAC 地址。")
    • pattern 正则表达式验证格式为 XX:XX:XX:XX:XX:XX 或 XX-XX-XX-XX-XX-XX 的 MAC 地址,其中 X 为十六进制数字(0-9、A-F、a-f)。

    • ^:匹配字符串的开头。

    • ([0-9A-Fa-f]{2}[:-]){5}:匹配五组两位十六进制数字后跟冒号或连字符的组合。

    • ([0-9A-Fa-f]{2}):匹配最后一组两位十六进制数字。

    • $:匹配字符串的结尾。

    此模式确保 MAC 地址由六组两位十六进制数字组成,各组之间用冒号或连字符分隔。可根据特定的 MAC 地址要求或格式变体进行调整。

    65.验证 URL

    使用正则表达式模式验证带可选协议的 URL。

    import re
    
    def validate_url(url):
        # 验证带可选协议的 URL 的正则表达式模式
        pattern = re.compile(r'^(?:(?:https?|ftp):\/\/)?[^\s\/$.?#].[^\s]*$')
    
        # 检查 URL 是否匹配模式
        return bool(pattern.match(url))
    
    # 测试用例
    urls = [
        "http://www.example.com",
        "https://example.com/path/to/page",
        "ftp://ftp.example.net",
        "www.example.org",
        "invalid url",
    ]
    
    for url in urls:
        if validate_url(url):
            print(f"{url} 是有效的 URL。")
        else:
            print(f"{url} 不是有效的 URL。")

    pattern 正则表达式验证带可选协议的 URL,各部分含义如下:

    • ^(?:(?:https?|ftp):\/\/)?:可选的非捕获组,用于匹配协议(http、https 或 ftp)及后跟的 "://"。

    • [^\s\/$.?#].[^\s]*$:匹配 URL 的其余部分,排除空白字符和某些特殊字符。

    66.匹配社会安全号码

    设计模式匹配并提取社会安全号码。

    import re
    
    def extract_social_security_numbers(text):
        # 匹配并提取社会安全号码的正则表达式模式
        pattern = re.compile(r'\b(\d{3}-\d{2}-\d{4})\b')
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(text)
    
        # 打印提取的社会安全号码
        print("提取的社会安全号码:")
        for match in matches:
            print(match)
    
    # 测试用例
    sample_text = """
    文本中的社会安全号码:123-45-6789、987-65-4321
    非社会安全号码:123-456-789、123-45-67890
    """
    
    extract_social_security_numbers(sample_text)
    • pattern 正则表达式捕获格式为 XXX-XX-XXXX 的社会安全号码,其中 X 为数字。

    • \b:单词边界,确保匹配完整的社会安全号码。

    67.提取哈希标签

    创建模式从文本中提取哈希标签。

    import re
    
    def extract_hashtags(text):
        # 匹配并提取哈希标签的正则表达式模式
        pattern = re.compile(r'\#\w+')
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(text)
    
        # 打印提取的哈希标签
        print("提取的哈希标签:")
        for match in matches:
            print(match)
    
    # 测试用例
    sample_text = """
    这是一条带 #sample 文本和 #hashtags 的内容。
    #DataScience 和 #MachineLearning 是有趣的话题。
    这里没有哈希标签。
    """
    
    extract_hashtags(sample_text)
    • pattern 正则表达式捕获以 '#' 符号开头,后跟一个或多个单词字符(\w+)的哈希标签。

    • \#:匹配 '#' 符号。

    • \w+:匹配一个或多个单词字符(字母、数字或下划线)。

    68.匹配 Python 文档字符串

    创建模式匹配代码中的 Python 文档字符串。

    import re
    
    def extract_python_docstrings(code):
        # 匹配 Python 文档字符串的正则表达式模式
        pattern = re.compile(r'(\'\'\'|\"\"\".*?\'\'\'|\"\"\".*?\"\"\")', re.DOTALL)
    
        # 在代码中查找所有匹配项
        matches = pattern.findall(code)
    
        # 打印提取的 Python 文档字符串
        print("提取的 Python 文档字符串:")
        for match in matches:
            print(match)
    
    # 测试用例
    sample_code = """
    def example_function():
        '''
        这是示例函数的文档字符串。
        它可以跨多行。
        '''
        pass
    
    class ExampleClass:
        \"\"\"
        ExampleClass 的文档字符串。
        它提供了关于该类的信息。
        \"\"\"
        def __init__(self):
            pass
    """
    
    extract_python_docstrings(sample_code)
    • pattern 正则表达式捕获用三重单引号或三重双引号(''' 或 """)括起来的文档字符串。re.DOTALL 标志用于使正则表达式中的点(.)匹配包括换行符在内的所有字符。

    此正则表达式模式提供了一种捕获 Python 文档字符串的基本方法,但需要注意的是,Python 文档字符串的格式多样(例如,可能带或不带三重引号、使用单引号或双引号等)。对于更可靠的解决方案,可考虑使用 ast 等专用的 Python 解析器或库从代码中提取文档字符串。

    69.匹配 Markdown 标题

    设计正则表达式模式匹配 Markdown 标题。

    import re
    
    def extract_markdown_headings(markdown_text):
        # 匹配不同级别 Markdown 标题的正则表达式模式
        heading_patterns = [
            re.compile(r'^#\s(.+)$', re.MULTILINE),      # 一级标题
            re.compile(r'^##\s(.+)$', re.MULTILINE),     # 二级标题
            re.compile(r'^###\s(.+)$', re.MULTILINE),    # 三级标题
            re.compile(r'^####\s(.+)$', re.MULTILINE),   # 四级标题
            re.compile(r'^#####\s(.+)$', re.MULTILINE),  # 五级标题
            re.compile(r'^######\s(.+)$', re.MULTILINE)  # 六级标题
        ]
    
        # 在文本中查找每个级别标题的所有匹配项
        for i, pattern in enumerate(heading_patterns, start=1):
            matches = pattern.findall(markdown_text)
            print(f"提取的 {i} 级标题:")
            for match in matches:
                print(match)
    
    # 测试用例
    sample_markdown = """
    # 一级标题
    
    ## 二级标题
    
    ### 三级标题
    
    #### 四级标题
    
    ##### 五级标题
    
    ###### 六级标题
    
    非标题:
    - 项目符号
    """
    
    extract_markdown_headings(sample_markdown)
    • 这些正则表达式模式使用 ^ 匹配行的开头,通过相应数量的 # 符号加空格来识别不同级别的标题。

    • (.+)$ 捕获标题的内容。

    70.验证十六进制颜色代码

    使用正则表达式模式验证十六进制颜色代码。

    import re
    
    def validate_hex_color_code(color_code):
        # 验证十六进制颜色代码的正则表达式模式
        pattern = re.compile(r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')
    
        # 检查颜色代码是否匹配模式
        return bool(pattern.match(color_code))
    
    # 测试用例
    color_codes = [
        "#123456",
        "#abc",
        "#fff",
        "#invalid",
    ]
    
    for color_code in color_codes:
        if validate_hex_color_code(color_code):
            print(f"{color_code} 是有效的十六进制颜色代码。")
        else:
            print(f"{color_code} 不是有效的十六进制颜色代码。")
    • pattern 正则表达式验证形式为 #RRGGBB 或 #RGB 的十六进制颜色代码,其中 R、G、B 为十六进制数字。

    • ^#:匹配字符串的开头和 '#' 符号。

    • ([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}):匹配六位或三位十六进制数字。

    • $:匹配字符串的结尾。

    71.匹配时间格式

    创建模式匹配 HH:MM:SS、HH:MM 格式的时间以及带 AM/PM 的变体形式。

    import re
    
    def extract_times(text):
        # 匹配不同格式时间的正则表达式模式
        time_patterns = [
            re.compile(r'\b([01]?[0-9]|2[0-3]):([0-5][0-9])(?::([0-5][0-9]))?\b'),  # HH:MM:SS 或 HH:MM
            re.compile(r'\b([01]?[0-9]|2[0-3]):([0-5][0-9])\s*([AaPp][Mm])?\b')      # HH:MM AM/PM
        ]
    
        # 在文本中查找每种时间模式的所有匹配项
        for i, pattern in enumerate(time_patterns, start=1):
            matches = pattern.findall(text)
            print(f"提取的时间(格式 {i}):")
            for match in matches:
                print(":".join(filter(None, match)))
    
    # 测试用例
    sample_text = """
    文本中的时间:12:34、23:45:56、9:15 AM、6:30 PM、18:45
    非时间:25:67、3:72、10:00 XYZ
    """
    
    extract_times(sample_text)

    第一种模式匹配 HH:MM:SS 或 HH:MM 格式的时间:

    • \b:单词边界,确保匹配完整的时间。

    • ([01]?[0-9]|2[0-3]):匹配小时(00 到 23)。

    • ([0-5][0-9]):匹配分钟(00 到 59)。

    • (?::([0-5][0-9]))?:可选地匹配以 :SS 形式表示的秒。

    第二种模式匹配 HH:MM AM/PM 格式的时间:

    • ([01]?[0-9]|2[0-3]):匹配小时(00 到 23)。

    • ([0-5][0-9]):匹配分钟(00 到 59)。

    • \s*([AaPp][Mm])?:可选地匹配 AM 或 PM。

    72.匹配嵌套括号

    设计模式匹配带指定深度嵌套括号的表达式。

    import re
    
    def extract_nested_brackets(text, depth):
        # 匹配带指定深度嵌套括号的表达式的正则表达式模式
        pattern = re.compile(rf'\((?:[^()]*|\((?:[^()]*|\((?:[^()]*|\((?:[^()]*|\([^()]*\))*\))*\))*\)){{{depth}}}\)')
    
        # 在文本中查找所有匹配项
        matches = pattern.findall(text)
    
        # 打印提取的带嵌套括号的表达式
        print("提取的带嵌套括号的表达式:")
        for match in matches:
            print(match)
    
    # 测试用例
    sample_text = """
    带嵌套括号的表达式:(a + (b * c) - d)
    另一个表达式:((x + y) / z) * (m - n)
    过深的表达式:(((p + q) - r) * s) / t
    """
    
    # 指定要匹配的嵌套括号深度
    nested_depth = 2
    
    extract_nested_brackets(sample_text, nested_depth)
    • pattern 正则表达式尝试匹配嵌套括号深度不超过指定值的表达式。

    • \( ... \):匹配一对括号。

    • (?: ... ):用于分组但不捕获的非捕获组。

    • [^()]*:匹配零个或多个除 '(' 和 ')' 之外的字符。

    • \((?:[^()]*|\((?:[^()]*|\((?:[^()]*|\((?:[^()]*|\([^()]*\))*\))*\))*\)):匹配嵌套深度不超过指定值的括号。

    需要注意的是,正则表达式并非解析括号等嵌套结构的最佳工具,尤其是当深度不固定时。对于更复杂的场景,可能需要使用解析器或更高级的方法。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐