引语
在物联网开发的世界里,串口数据如同流淌的数字血液,每一行字符都藏着环境监测的秘密。当你面对[321022] T:25 C H:68% L:0%
这样的数据流时,正则表达式就像一把精准的瑞士军刀 —— 它能从混乱的字符中切割出时间戳、温度、湿度等关键信息,让 STM32 传感器的数据乖乖 “对号入座”。
本文将带你拆解正则表达式的核心语法,从\d+
匹配数字到()
捕获组提取数据,再到通过re.match()
从字符串开头精准锁定目标。无论你是想解析气象监测数据,还是开发传感器数据管理系统,掌握这把 “数字手术刀”,就能让每一行串口输出都成为可解读的洞察,让代码在数据洪流中开辟出清晰的航道。
点关注不迷路哟。你的点赞、收藏,一键三连,是我持续更新的动力哟!!!
主页:
一位搞嵌入式的 genius-CSDN博客https://blog.csdn.net/m0_73589512?spm=1000.2115.3001.5343
目录
2. execute(self, query, args=None) 方法解析
13. 函数 match(pattern, string, flags=0) 解析
python自动化采集数据脚本:常用函数解析
1. fetchone(self)
方法解析
def fetchone(self): """Fetch the next row.""" self._check_executed() if self._rows is None or self.rownumber >= len(self._rows): return None result = self._rows[self.rownumber] self.rownumber += 1 return result
功能说明
获取查询结果的下一行数据:从结果集中按顺序获取一行数据
关键逻辑:
self._check_executed()
:检查是否已执行查询(防止未查询就获取数据)检查结果集是否存在(
self._rows is None
)或是否已取完数据(rownumber >= len(self._rows)
)若数据存在,返回当前行(
self._rows[self.rownumber]
)并将行号(rownumber
)加 1
返回值:
成功:返回结果集中的下一行数据(元组或字典)
失败:返回
None
(无更多数据或查询未执行)
使用场景
逐行处理查询结果(如需要控制数据读取节奏时)
示例:
cursor.execute("SELECT * FROM users") row = cursor.fetchone() while row: print(row) row = cursor.fetchone()
2. execute(self, query, args=None)
方法解析
def execute(self, query, args=None): """Execute a query. :param query: Query to execute. :type query: str :param args: Parameters used with query. (optional) :type args: tuple, list or dict :return: Number of affected rows. :rtype: int """ while self.nextset(): pass query = self.mogrify(query, args) result = self._query(query) self._executed = query return result
功能说明
执行 SQL 查询语句:接收 SQL 查询和参数,执行后返回受影响的行数
关键逻辑:
while self.nextset(): pass
:跳过之前查询的结果集(处理多结果集场景)query = self.mogrify(query, args)
:将参数绑定到 SQL 查询中(防 SQL 注入)result = self._query(query)
:执行实际的查询操作记录已执行的查询(
self._executed = query
)并返回受影响行数
参数说明:
query
:SQL 查询语句(如SELECT * FROM users WHERE id = %s
)args
:查询参数(支持tuple/list
(对应%s
)或dict
(对应%(name)s
))
使用场景
执行增删改查操作(INSERT/UPDATE/DELETE/SELECT)
示例:
# 使用tuple参数 cursor.execute("INSERT INTO users(name, age) VALUES(%s, %s)", ("张三", 25)) # 使用dict参数 cursor.execute("SELECT * FROM users WHERE age > %(min_age)s", {"min_age": 18})
3. commit(self)
方法解析
def commit(self): """ Commit changes to stable storage. See `Connection.commit() <https://www.python.org/dev/peps/pep-0249/#commit>`_ in the specification. """ self._execute_command(COMMAND.COM_QUERY, "COMMIT") self._read_ok_packet()
功能说明
提交事务:将未提交的事务变更持久化到数据库
关键逻辑:
self._execute_command(COMMAND.COM_QUERY, "COMMIT")
:发送 COMMIT 命令到数据库self._read_ok_packet()
:读取数据库返回的确认包(确保提交成功)
重要性:
若不调用
commit()
,事务中的变更不会保存到数据库通常在执行 INSERT/UPDATE/DELETE 后需要调用
使用场景
数据库事务管理:
try: cursor.execute("BEGIN") # 开始事务 cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1") cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2") connection.commit() # 提交事务 except: connection.rollback() # 回滚事务
4. 整体逻辑总结
这三个方法是数据库游标(Cursor)的核心功能,对应 Python 数据库 API 规范(PEP-249)中的标准接口:
execute()
:执行 SQL 查询,支持参数化查询fetchone()
:按顺序获取查询结果的下一行commit()
:提交事务,确保数据变更持久化
游标工作流程示例
# 1. 执行查询 cursor.execute("SELECT id, name FROM users WHERE age > 18") # 2. 逐行获取结果 row1 = cursor.fetchone() # 获取第一行 row2 = cursor.fetchone() # 获取第二行 # 3. 提交事务(若有变更) connection.commit()
5. 扩展知识:游标与连接的关系
游标(Cursor):
用于执行 SQL 语句和遍历结果集的对象
每个游标独立维护查询状态(如当前行号)
连接(Connection):
与数据库的物理连接,管理事务状态
多个游标可共享同一个连接
最佳实践:
用完游标后及时关闭(
cursor.close()
)事务完成后及时提交或回滚
避免长时间持有数据库连接
6. 正则表达式基本语法规则
正则表达式是一种用于匹配文本模式的工具,由普通字符和特殊字符(元字符)组成。以下是核心规则:
7. 正常数据正则表达式解析
normal_pattern = r'\[(\d+)\]\s+T:(\d+)\s*C\s+H:(\d+)\s*%\s+L:(\d+)\s*%'
模式分解说明
模式部分 | 解释 |
---|---|
r'\[' | 匹配左方括号[ (r 表示原始字符串,避免\ 转义问题) | | (\d+) | 捕获组1:匹配1个或多个数字(时间戳) | | \] |
匹配右方括号] |
\s+ |
匹配 1 个或多个空白字符(空格、制表符等) |
T: |
匹配文本T: |
(\d+) |
捕获组 2:匹配温度值(整数) |
\s* |
匹配 0 个或多个空白字符 |
C |
匹配温度单位C |
\s+ |
匹配 1 个或多个空白字符 |
H: |
匹配文本H: |
(\d+) |
捕获组 3:匹配湿度值(整数) |
\s*% |
匹配湿度单位% (允许前后有空白) |
\s+ |
匹配 1 个或多个空白字符 |
L: |
匹配文本L: |
(\d+) |
捕获组 4:匹配光照值(整数) |
\s*% |
匹配光照单位% (允许前后有空白) |
匹配示例
输入:
[321022] T:25 C H:68% L:0%
匹配结果:
捕获组 1:
321022
(时间戳)捕获组 2:
25
(温度)捕获组 3:
68
(湿度)捕获组 4:
0
(光照)
8. 错误数据正则表达式解析
error_pattern = r'\[(\d+)\]\s+DHT11\s+Error!\s+L:(\d+)\s*%'
模式分解说明
模式部分 | 解释 |
---|---|
r'\[' | 匹配左方括号[ | | (\d+) | 捕获组1:匹配时间戳 | | \] |
匹配右方括号] |
\s+ |
匹配 1 个或多个空白字符 |
DHT11 |
匹配文本DHT11 |
\s+ |
匹配 1 个或多个空白字符 |
Error! |
匹配文本Error! |
\s+ |
匹配 1 个或多个空白字符 |
L: |
匹配文本L: |
(\d+) |
捕获组 2:匹配光照值(整数) |
\s*% |
匹配光照单位% (允许前后有空白) |
匹配示例
输入:
[405018] DHT11 Error! L:2%
匹配结果:
捕获组 1:
405018
(时间戳)捕获组 2:
2
(光照)
9. 正则表达式核心元字符说明
元字符 | 含义 |
---|---|
\ |
转义字符,用于匹配特殊字符(如[ 、] 、\s 等) |
[] |
字符集,匹配方括号内的任意字符(如[0-9] 匹配数字) |
() |
捕获组,用于提取匹配的子字符串(如(\d+) 提取数字) |
\d |
匹配数字(等价于[0-9] ) |
\s |
匹配空白字符(空格、制表符、换行符等) |
+ |
量词:匹配 1 次或多次(如\d+ 匹配至少 1 个数字) |
* |
量词:匹配 0 次或多次(如\s* 匹配 0 个或多个空白) |
\A |
匹配字符串开头 |
\Z |
匹配字符串结尾 |
| |
或操作(如a|b 匹配a 或b ) |
10. 扩展:正则表达式进阶写法
1. 匹配小数温度(如 25.5°C)
normal_pattern = r'\[(\d+)\]\s+T:(\d+\.\d+|\d+)\s*C\s+H:(\d+)\s*%\s+L:(\d+)\s*%'
(\d+\.\d+|\d+)
:匹配整数或小数(如25
或25.5
)
2. 匹配更灵活的空白字符
normal_pattern = r'\[(\d+)\](\s+)T:(\d+)\s*C\s*H:(\d+)\s*%\s*L:(\d+)\s*%'
(\s+)
:明确匹配时间戳后的空白字符
3. 添加行首尾匹配
normal_pattern = r'^\[(\d+)\]\s+T:(\d+)\s*C\s+H:(\d+)\s*%\s+L:(\d+)\s*%$'
^
:匹配行开头$
:匹配行结尾,确保整行完全匹配
11. 正则表达式测试方法
推荐使用在线工具测试正则表达式,例如:
测试步骤
输入正则表达式
输入测试字符串
查看匹配结果和捕获组内容
根据结果调整正则表达式
12. 正则表达式最佳实践
使用原始字符串:
r'\[(\d+)\]' # 推荐,避免\转义问题 '\[(\d+)\]' # 不推荐,需处理\转义
明确匹配范围:
尽量使用
^
和$
匹配行首尾,避免部分匹配示例:
^Pattern$
比Pattern
更精确
分组清晰:
按逻辑分组,便于后续提取数据
不需要提取的分组使用非捕获组:
(?:pattern)
逐步构建:
先编写简单模式,再逐步添加复杂条件
例如:先匹配时间戳
\[\d+\]
,再添加温度部分T:\d+C
通过理解这些规则,可以根据实际数据格式灵活调整正则表达式,确保准确匹配和数据提取。如果需要匹配更复杂的格式,可逐步扩展模式并通过测试验证匹配效果。
13. 函数 match(pattern, string, flags=0)
解析
这个函数是 Python 中 re
模块的 match()
函数实现,用于从字符串开头尝试匹配正则表达式模式。以下是对其功能、参数和实现逻辑的详细解析:
一、函数功能概述
def match(pattern, string, flags=0): """Try to apply the pattern at the start of the string, returning a Match object, or None if no match was found.""" return _compile(pattern, flags).match(string)
核心功能:从字符串的开头开始尝试匹配正则表达式模式
返回值:
匹配成功:返回
Match
对象(包含匹配结果和分组信息)匹配失败:返回
None
关键调用:
_compile(pattern, flags)
:编译正则表达式模式match(string)
:在字符串上执行匹配操作
二、参数详解
参数 | 类型 | 说明 |
---|---|---|
pattern |
str | 正则表达式模式字符串(如 r'\d+' 匹配数字) |
string |
str | 要匹配的目标字符串(如 "123abc" ) |
flags |
int | 匹配标志(可选,默认 0),用于修改匹配行为,例如: |
- re.I :忽略大小写 - re.M :多行匹配 - re.S :点号匹配所有字符 |
三、实现逻辑解析
正则表达式编译:
_compile(pattern, flags)
将字符串形式的正则表达式
pattern
编译为内部可执行的模式对象编译后可提高匹配效率(避免重复编译相同模式)
字符串匹配:
.match(string)
对
string
执行匹配操作,仅从字符串开头开始匹配若开头不匹配模式,则直接返回
None
,不继续向后匹配
示例说明:
import re # 匹配成功 result = re.match(r'\d+', '123abc') print(result.group()) # 输出: '123' # 匹配失败(开头不是数字) result = re.match(r'\d+', 'abc123') print(result) # 输出: None
四、与其他匹配函数的对比
函数 | 匹配位置 | 示例(模式\d+ ,字符串'abc123' ) |
---|---|---|
re.match() |
字符串开头 | 匹配失败(返回None ) |
re.search() |
字符串任意位置 | 匹配成功(返回'123' ) |
re.findall() |
查找所有匹配 | 返回['123'] |
五、flags 参数常用取值
re.match(r'abc', 'ABC', re.I).group() # 输出: 'ABC'
多行匹配(
re.M
):pattern = r'^Hello' string = """Hello World Hello Python""" # 不使用re.M时仅匹配第一行 re.match(pattern, string).group() # 输出: 'Hello' # 使用re.M时匹配所有行开头 re.match(pattern, string, re.M) # 仍只匹配第一行(match()仅从开头匹配) re.findall(pattern, string, re.M) # 输出: ['Hello', 'Hello']
点号匹配所有字符(
re.S
):pattern = r'Hello.*World' string = "Hello\nWorld" re.match(pattern, string).group() # 匹配失败(.不匹配\n) re.match(pattern, string, re.S).group() # 匹配成功(.匹配\n)
六、Match 对象常用方法和属性
方法 / 属性 | 说明 |
---|---|
group(n) |
获取第 n 个捕获组的匹配结果(n=0 为整个匹配结果) |
groups() |
以元组形式返回所有捕获组的结果 |
groupdict() |
以字典形式返回命名捕获组的结果 |
start(n) |
获取第 n 个捕获组的起始位置 |
end(n) |
获取第 n 个捕获组的结束位置 |
span(n) |
获取第 n 个捕获组的起始和结束位置(返回元组(start, end) ) |
七、使用场景建议
明确需要从开头匹配时:
验证字符串格式(如 IP 地址、邮箱等)
示例:验证手机号(开头为 13/14/15/18 等)
def is_valid_phone(phone): return re.match(r'^1[3-9]\d{9}$', phone) is not None
与其他匹配函数配合使用:
先使用
match()
尝试开头匹配,失败后再用search()
全局搜索
def find_pattern(pattern, string): result = re.match(pattern, string) if not result: result = re.search(pattern, string) return result
结合 flags 参数处理复杂场景:
处理包含特殊字符或需要多行匹配的文本
八、注意事项
仅开头匹配限制:
match()
不会搜索字符串中间的匹配项,若需要全局匹配请使用re.search()
编译后的模式对象:
对于频繁使用的正则表达式,建议提前编译以提高效率:
pattern = re.compile(r'\d+') result = pattern.match('123abc')
转义字符处理:
使用原始字符串(
r''
)避免转义问题:
re.match(r'\\d+', '\\d123') # 匹配'\\d' re.match('\\\\d+', '\\d123') # 等价于上面的原始字符串
通过理解match()
函数的工作原理和参数用法,可以更精准地控制正则表达式的匹配行为,尤其是在需要从字符串开头进行模式匹配的场景中。