当前位置: 首页 > news >正文

Python 正则表达式 re.findall()

re.findall() 是 Python re 模块中用于查找字符串中所有匹配正则表达式模式的子串的方法。与 re.search() 只返回第一个匹配项不同,findall() 会返回所有匹配项。

基本语法

re.findall(pattern, string, flags=0)

参数说明:

  • pattern: 正则表达式模式
  • string: 要搜索的字符串
  • flags: 可选标志,如 re.IGNORECASEre.MULTILINE

返回值:

  • 如果模式中有分组,返回分组元组的列表
  • 如果模式中没有分组,返回所有匹配子串的列表
  • 如果没有找到匹配,返回空列表

1. 基本查找用法

示例1:查找所有数字

import retext = "There are 3 apples and 5 oranges"
numbers = re.findall(r'\d+', text)
print(numbers)  # 输出: ['3', '5']

示例2:查找所有单词

text = "Hello world! Python is awesome."
words = re.findall(r'\w+', text)
print(words)  # 输出: ['Hello', 'world', 'Python', 'is', 'awesome']

2. 使用分组时的行为

示例3:无分组情况

text = "John: 30, Jane: 25, Bob: 42"
ages = re.findall(r': \d+', text)
print(ages)  # 输出: [': 30', ': 25', ': 42']

示例4:有分组情况(返回分组内容)

text = "John: 30, Jane: 25, Bob: 42"
ages = re.findall(r': (\d+)', text)
print(ages)  # 输出: ['30', '25', '42']

示例5:多个分组情况

text = "John: 30, Jane: 25, Bob: 42"
info = re.findall(r'(\w+): (\d+)', text)
print(info)  # 输出: [('John', '30'), ('Jane', '25'), ('Bob', '42')]

3. 使用正则表达式高级特性

示例6:非贪婪匹配

html = "<div>content1</div><div>content2</div>"
contents = re.findall(r'<div>(.*?)</div>', html)
print(contents)  # 输出: ['content1', 'content2']

示例7:使用字符类

text = "Colors: red, green, BLUE, Yellow"
colors = re.findall(r'[a-zA-Z]+', text)
print(colors)  # 输出: ['Colors', 'red', 'green', 'BLUE', 'Yellow']

示例8:使用边界匹配

text = "cat category concatenate"
words = re.findall(r'\bcat\b', text)
print(words)  # 输出: ['cat']

4. 使用标志(flags)

示例9:忽略大小写

text = "Apple orange BANANA Grape"
fruits = re.findall(r'[a-z]+', text, re.IGNORECASE)
print(fruits)  # 输出: ['Apple', 'orange', 'BANANA', 'Grape']

示例10:多行模式

text = """First line
Second line
Third line"""
lines = re.findall(r'^\w+', text, re.MULTILINE)
print(lines)  # 输出: ['First', 'Second', 'Third']

5. 实际应用场景

示例11:提取电子邮件地址

text = "Contact us at info@example.com or support@test.org"
emails = re.findall(r'[\w\.-]+@[\w\.-]+', text)
print(emails)  # 输出: ['info@example.com', 'support@test.org']

示例12:提取URL链接

text = "Visit https://www.example.com or http://test.org"
urls = re.findall(r'https?://[^\s/$.?#].[^\s]*', text)
print(urls)  # 输出: ['https://www.example.com', 'http://test.org']

示例13:解析日志文件

log = """
2023-04-15 10:00:00 INFO System started
2023-04-15 10:01:23 ERROR Database connection failed
2023-04-15 10:02:45 WARNING Disk space low
"""
errors = re.findall(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} ERROR (.+)', log)
print(errors)  # 输出: ['Database connection failed']

示例14:提取HTML标签内容

html = "<h1>Title</h1><p>Paragraph 1</p><p>Paragraph 2</p>"
paragraphs = re.findall(r'<p>(.*?)</p>', html)
print(paragraphs)  # 输出: ['Paragraph 1', 'Paragraph 2']

示例15:提取电话号码

text = "Call 123-456-7890 or 987.654.3210"
phones = re.findall(r'\d{3}[-.]\d{3}[-.]\d{4}', text)
print(phones)  # 输出: ['123-456-7890', '987.654.3210']

示例16:提取货币金额

text = "Prices: $12.99, €9.99, ¥1000"
prices = re.findall(r'[\$€¥]\d+\.?\d*', text)
print(prices)  # 输出: ['$12.99', '€9.99', '¥1000']

示例17:提取日期

text = "Dates: 2023-04-15, 15/04/2023, 04.15.2023"
dates = re.findall(r'\d{4}[-/.]\d{2}[-/.]\d{2}|\d{2}[-/.]\d{2}[-/.]\d{4}', text)
print(dates)  # 输出: ['2023-04-15', '15/04/2023', '04.15.2023']

6. 高级技巧

示例18:使用命名分组

text = "User: john_doe, Age: 30; User: jane_smith, Age: 25"
users = re.findall(r'User: (?P<name>\w+), Age: (?P<age>\d+)', text)
print(users)  # 输出: [('john_doe', '30'), ('jane_smith', '25')]

示例19:复杂模式匹配

text = "Coordinates: (12.345, -67.890), (0, 42.123)"
coords = re.findall(r'\(([^,]+),\s*([^)]+)\)', text)
print(coords)  # 输出: [('12.345', '-67.890'), ('0', '42.123')]

示例20:使用正向预查

text = "apple orange banana grape"
fruits_before_banana = re.findall(r'\w+(?=\sbanana)', text)
print(fruits_before_banana)  # 输出: ['orange']

7. 注意事项

  1. re.findall() 返回的是字符串列表或元组列表,不是匹配对象
  2. 当模式中有分组时,只返回分组内容,不是整个匹配
  3. 对于大文本,考虑使用 re.finditer() 节省内存
  4. 复杂的正则表达式可能会影响性能
  5. 处理HTML/XML等结构化数据时,最好使用专门的解析器

示例21:与 re.finditer() 对比

text = "Error 404, Error 500, Warning 302"# 使用 findall
codes = re.findall(r'Error (\d+)', text)
print(codes)  # 输出: ['404', '500']# 使用 finditer
for match in re.finditer(r'Error (\d+)', text):print(f"Found at {match.start()}-{match.end()}: {match.group(1)}")
# 输出:
# Found at 0-8: 404
# Found at 10-18: 500

8. 性能优化建议

  1. 预编译常用正则表达式:

    pattern = re.compile(r'\d+')
    numbers = pattern.findall(text)
    
  2. 尽量使用具体模式而非宽泛模式:

    # 不好的写法
    re.findall(r'.*:\s*(.*)', text)# 更好的写法
    re.findall(r'\w+:\s*(\w+)', text)
    
  3. 避免过度使用回溯:

    # 可能导致性能问题的写法
    re.findall(r'(a+)+$', text)
    

Python re.findall() 方法中的 flags 参数详解

re.findall() 方法的 flags 参数可以修改正则表达式的匹配行为,使其更灵活地适应不同的文本处理需求。下面我将详细介绍各种 flag 的用法和实际应用场景。

1. 常用 flags 概览

标志常量简写描述
re.IGNORECASEre.I忽略大小写
re.MULTILINEre.M多行模式,影响 ^$
re.DOTALLre.S使 . 匹配包括换行符在内的所有字符
re.VERBOSEre.X允许编写更易读的正则表达式
re.ASCIIre.A使 \w, \W, \b, \B, \d, \D, \s, \S 只匹配 ASCII 字符
re.LOCALEre.L使 \w, \W, \b, \B 依赖当前区域设置
re.UNICODEre.U使 \w, \W, \b, \B, \d, \D, \s, \S 匹配 Unicode 字符

2. 各 flag 详细说明及示例

2.1 re.IGNORECASE (re.I) - 忽略大小写

作用:使匹配对大小写不敏感

示例

import retext = "Apple banana ORANGE Grape"
# 不使用 IGNORECASE
result = re.findall(r'apple', text)
print(result)  # []# 使用 IGNORECASE
result = re.findall(r'apple', text, re.IGNORECASE)
print(result)  # ['Apple']# 匹配所有水果名(忽略大小写)
fruits = re.findall(r'[a-z]+', text, re.I)
print(fruits)  # ['Apple', 'banana', 'ORANGE', 'Grape']
2.2 re.MULTILINE (re.M) - 多行模式

作用:改变 ^$ 的行为,使它们分别匹配每一行的开头和结尾

示例

text = """First line
Second line
Third line"""# 不使用 MULTILINE
result = re.findall(r'^\w+', text)
print(result)  # ['First']# 使用 MULTILINE
result = re.findall(r'^\w+', text, re.MULTILINE)
print(result)  # ['First', 'Second', 'Third']# 匹配每行末尾的单词
result = re.findall(r'\w+$', text, re.M)
print(result)  # ['line', 'line', 'line']
2.3 re.DOTALL (re.S) - 点号匹配所有模式

作用:使 . 匹配包括换行符在内的所有字符

示例

text = """Start
Middle
End"""# 不使用 DOTALL
result = re.findall(r'Start.*End', text)
print(result)  # []# 使用 DOTALL
result = re.findall(r'Start.*End', text, re.DOTALL)
print(result)  # ['Start\nMiddle\nEnd']# 提取多行注释内容
html = """<!-- 
这是多行
HTML注释 
-->"""
comment = re.findall(r'<!--(.*?)-->', html, re.DOTALL)
print(comment)  # [' \n这是多行\nHTML注释 \n']
2.4 re.VERBOSE (re.X) - 详细模式

作用:允许在正则表达式中添加空白和注释,使其更易读

示例

# 复杂的电话号码正则表达式
phone_re = re.compile(r'''^(\+\d{1,3})?       # 国际区号[-\s]?              # 分隔符(\d{3})             # 前3位[-\s]?              # 分隔符(\d{3,4})           # 中间3或4位[-\s]?              # 分隔符(\d{4})             # 最后4位$''', re.VERBOSE)text = "Phone numbers: +86-138-1234-5678, 010-87654321"
numbers = phone_re.findall(text)
print(numbers)  # [('+86', '138', '1234', '5678'), ('', '010', '8765', '4321')]
2.5 re.ASCII (re.A) - ASCII 模式

作用:使 \w, \W, \b, \B, \d, \D, \s, \S 只匹配 ASCII 字符

示例

text = "Python3 中文 Español café"# 默认模式(Unicode)
result = re.findall(r'\w+', text)
print(result)  # ['Python3', '中文', 'Español', 'café']# ASCII 模式
result = re.findall(r'\w+', text, re.ASCII)
print(result)  # ['Python3', 'Espa', 'ol', 'caf']
2.6 re.UNICODE (re.U) - Unicode 模式

作用:使 \w, \W, \b, \B, \d, \D, \s, \S 匹配 Unicode 字符(Python 3 默认)

示例

text = "Русский 中文 ελληνικά"# 默认就是 UNICODE 模式
result = re.findall(r'\w+', text)
print(result)  # ['Русский', '中文', 'ελληνικά']# 显式指定 UNICODE
result = re.findall(r'\w+', text, re.UNICODE)
print(result)  # ['Русский', '中文', 'ελληνικά']
2.7 re.LOCALE (re.L) - 区域设置模式

作用:使 \w, \W, \b, \B 依赖当前区域设置(不推荐使用)

示例

import locale# 设置区域为德语
locale.setlocale(locale.LC_ALL, 'de_DE.UTF-8')text = "straße café"
result = re.findall(r'\w+', text, re.LOCALE)
print(result)  # ['straße', 'café']

3. 组合使用多个 flags

可以通过按位或 (|) 操作符组合多个 flags

示例

text = """Name: John
AGE: 30
name: Jane
age: 25"""# 同时使用 IGNORECASE 和 MULTILINE
results = re.findall(r'^name:\s*(\w+)', text, re.I | re.M)
print(results)  # ['John', 'Jane']# 解析多行配置项
config = """[Server]
host = example.com
port = 8080
timeout = 30"""settings = re.findall(r'^(\w+)\s*=\s*(.*)$', config, re.MULTILINE | re.VERBOSE
)
print(settings)  # [('host', 'example.com'), ('port', '8080'), ('timeout', '30')]

4. 实际应用场景

4.1 解析日志文件(多行模式)

log = """2023-04-15 10:00:00 [INFO] System started
2023-04-15 10:01:23 [ERROR] Database connection failed
2023-04-15 10:02:45 [WARN] Disk space low"""# 提取所有错误日志(带时间戳)
errors = re.findall(r'^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[ERROR\] (.*)$',log,re.MULTILINE
)
print(errors)  # [('2023-04-15 10:01:23', 'Database connection failed')]
4.2 提取HTML内容(点号匹配所有)
html = """<div><p>First paragraph</p><p>Second paragraph</p>
</div>"""# 提取所有段落内容
paragraphs = re.findall(r'<p>(.*?)</p>',html,re.DOTALL  # 使 . 匹配换行符
)
print(paragraphs)  # ['First paragraph', 'Second paragraph']
4.3 多语言文本处理(Unicode模式)
text = "English: hello, 中文: 你好, Français: bonjour"# 提取所有非ASCII单词
words = re.findall(r'[^\x00-\x7F]+',  # 匹配非ASCII字符text,re.UNICODE
)
print(words)  # ['你好', 'bonjour']
4.4 复杂模式匹配(详细模式)
# 匹配各种格式的日期
date_re = re.compile(r'''^(?:20\d{2}|19\d{2})  # 年份 1900-2099[-/.]                # 分隔符(?:0[1-9]|1[0-2])    # 月份 01-12[-/.]                # 分隔符(?:0[1-9]|[12][0-9]|3[01])  # 日 01-31$''', re.VERBOSE)dates = ["2023-04-15", "1999/12/31", "2000.01.01"]
valid_dates = [d for d in dates if date_re.search(d)]
print(valid_dates)  # ['2023-04-15', '1999/12/31', '2000.01.01']

5. 注意事项

  1. flag 的作用范围:flags 会影响整个正则表达式的行为
  2. flag 的组合:多个 flags 可以组合使用,但要注意它们之间的交互
  3. 性能考虑:某些 flags(如 re.UNICODE)可能会影响性能
  4. 预编译正则表达式:频繁使用的正则表达式应该先编译再使用
    pattern = re.compile(r'your_pattern', flags=re.I | re.M)
    results = pattern.findall(text)
    
  5. Python 3 的默认行为:在 Python 3 中,re.UNICODE 是默认启用的

通过合理使用这些 flags,你可以编写出更强大、更灵活的正则表达式,适应各种复杂的文本处理需求。

http://www.dtcms.com/a/327241.html

相关文章:

  • special topic 11 (1)
  • 【Linux系统】详解Ext2,文件系统
  • 打印流水号条形码
  • 标注工具组件功能文档
  • 如何将新建的Anaconda虚拟环境导入Juputer内核中?
  • Spring Boot项目通过RestTemplate调用三方接口详细教程
  • 系统架构设计师备考之架构设计实践知识
  • 完整反作弊系统架构(技术讲解)
  • 如何解决Unexpected token ‘<’, “<!doctype “… is not valid JSON 报错问题
  • MyBatis持久层实现
  • 人工智能概念:常见的大模型微调方法
  • Web学习笔记5
  • Java设计模式-快速入门
  • LeetCode算法领域经典入门题目之“Two Sum”问题
  • 1.4.1 副驾驶(Copilot)模式:让人工智能大模型成为你的指导和建议者
  • 从零开始之stm32之CAN通信
  • 聚合搜索中的设计模式
  • 鲲鹏arm服务器安装neo4j社区版,实现图书库自然语言检索基础
  • leetcode49.字母异位词分组
  • NLP—词向量转换评论学习项目分析真实案例
  • 本地(macOS)和服务器时间不同步导致的 Bug排查及解决
  • linux 执行ls命令文件夹显示全白色
  • 微前端架构:原理、场景与实践案例
  • Rust 性能提升“最后一公里”:详解 Profiling 瓶颈定位与优化|得物技术
  • 计算机视觉(6)-自动驾驶感知方案对比
  • 使用 NetBird 创建安全的私有网络,简化远程连接!
  • Golang 语言中 Context 的使用方式
  • Rust学习笔记(二)|变量、函数与控制流
  • 【七指共振擒牛战法】副图+选股指标——多维度捕捉主升浪的量化交易利器
  • 智慧校园|智慧校园管理小程序|基于微信小程序的智慧校园管理系统设计与实现(源码+数据库+文档)