正则表达式——捕获组用法(示例 + 解释)

基础概念

  • 分组和捕获

  • 小括号 () 用于分组。分组不仅可以将多个字符视为一个整体,还可以捕获匹配的子字符串
  • 例如,正则表达式 (abc) 会匹配并捕获字符串 "abc"

  • 捕获组

  • 每一对括号会创建一个捕获组。
  • 捕获组会被自动编号,编号从1开始。组0是整个正则表达式的匹配结果。
  • 可以使用反向引用引用捕获组,例如 \1 引用第一个捕获组。

捕获组的初级用法——First

捕获组的具体功能

  • 捕获和引用

    • 可以在匹配后使用 group(n) 方法获取第 n 个捕获组的内容。例如,re.search(r'(\d+)', '123abc').group(1) 会返回 "123"
    • 捕获组可以在正则表达式中被反向引用。例如,(\d+)\s\1 匹配两个相同的数字序列,中间有一个空格。
import re

pattern = r'(\d+)-(\d+)-(\d+)'
text = "2024-05-23"
match = re.match(pattern, text)
if match:
    print(match.group(0))  # 整个匹配 "2024-05-23"
    print(match.group(1))  # 第一个捕获组 "2024"
    print(match.group(2))  # 第二个捕获组 "05"
    print(match.group(3))  # 第三个捕获组 "23"


  • 非捕获组

    • 使用 (?:...) 可以创建非捕获组。这种分组不会捕获匹配的子字符串,不会创建编号的组,但仍然会对模式进行分组。
    • 例如,(?:abc) 匹配 "abc",但不会捕获它。
import re

pattern = r'(?:abc)+'
text = "abcabc"
match = re.match(pattern, text)
if match:
    print(match.group(0))  # "abcabc"

  • 命名捕获组

    • 使用 (?P<name>...) 可以创建命名捕获组。
    • 可以使用名字来引用捕获组,而不是数字。
    • 例如,(?P<word>\w+) 可以通过 group('word') 获取匹配的内容。
import re

pattern = r'(?P<year>\d+)-(?P<month>\d+)-(?P<day>\d+)'
text = "2024-05-23"
match = re.match(pattern, text)
if match:
    print(match.group('year'))  # "2024"
    print(match.group('month'))  # "05"
    print(match.group('day'))    # "23"

  • 后向引用

    • 后向引用指的是在正则表达式中引用之前捕获的组
    • 使用反斜杠加组号 \1 引用第一个捕获组,\2 引用第二个捕获组,以此类推。
import re

pattern = r'(\b\w+\b) \1'
text = "hello hello"
match = re.search(pattern, text)
if match:
    print(match.group(0))  # "hello hello"

捕获组的应用场景

  • 数据提取

    • 从文本中提取特定格式的数据,例如日期、时间、URL、电子邮件地址等。

  • 数据验证

    • 验证输入数据的格式是否正确,例如电话号码、邮政编码等。

  • 文本替换

    • 使用捕获组和反向引用可以在替换操作中重用部分匹配的文本。
  • 复杂模式匹配

    • 捕获组可以帮助处理复杂的模式,例如嵌套结构、递归模式等。


捕获组的高级用法——Second

  • 嵌套捕获组:

    • 捕获组可以嵌套使用,组号是按照左括号的出现顺序分配。
import re

pattern = r'((\d{4})-(\d{2})-(\d{2}))'
text = "2024-05-23"
match = re.match(pattern, text)
if match:
    print(match.group(0))  # "2024-05-23" (整体匹配)
    print(match.group(1))  # "2024-05-23" (第一个捕获组)
    print(match.group(2))  # "2024" (第二个捕获组)
    print(match.group(3))  # "05" (第三个捕获组)
    print(match.group(4))  # "23" (第四个捕获组)

  • 后向引用的高级用法:

    • 后向引用可以在正则表达式中多次引用捕获组,用于匹配重复的模式
import re

pattern = r'<(\w+)>(.*?)</\1>'
text = "<div>Content</div>"
match = re.match(pattern, text)
if match:
    print(match.group(0))  # "<div>Content</div>"
    print(match.group(1))  # "div"
    print(match.group(2))  # "Content"

  • 条件匹配:

    • 条件匹配可以基于捕获组是否匹配来决定使用哪种模式。条件匹配的语法是 (?(id/name)yes-pattern|no-pattern)

import re

pattern = r'(\d{3})?(\d{3})-(\d{4})(?(1)-(\d{4}))'
text = "123-456-7890"
match = re.match(pattern, text)
if match:
    print(match.group(0))  # "123-456-7890"
    print(match.group(1))  # None
    print(match.group(2))  # "123"
    print(match.group(3))  # "456"
    print(match.group(4))  # "7890"

  • 非贪婪匹配:

    • 捕获组默认是贪婪的,尽可能多地匹配字符。可以使用 ? 将其转换为非贪婪匹配

import re

pattern = r'<(.*?)>'
text = "<div>Content</div>"
match = re.match(pattern, text)
if match:
    print(match.group(0))  # "<div>"
    print(match.group(1))  # "div"

  • 特殊情况处理:

    • 转义字符

      在捕获组中,某些字符(如 (, ), [, ], {, }, \, ^, $, |, ?, *, +, .需要转义

    • import re
      
      pattern = r'\((\d+)\)'
      text = "(123)"
      match = re.match(pattern, text)
      if match:
          print(match.group(1))  # "123"
      

    • 忽略大小写

      可以使用 're.IGNORECASE' 标志来忽略大小写

    • import re
      
      pattern = r'(?i)abc'
      text = "ABC"
      match = re.match(pattern, text)
      if match:
          print(match.group(0))  # "ABC"
      
    • 多行匹配

      可以使用 're.MULTILINE' 标志,使 ^$ 匹配每一行的开头和结尾

    • import re
      
      pattern = r'^(.*)$'
      text = "First line\nSecond line"
      matches = re.findall(pattern, text, re.MULTILINE)
      print(matches)  # ['First line', 'Second line']
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值