
在Qt5中,QRegularExpression是处理字符串匹配和提取的核心工具。
以下是 QRegularExpression的深度详解:
1. 为什么要用 QRegularExpression?(历史背景)
在 Qt 5 之前,Qt 使用的是 QRegExp。但在新的Qt项目中,强烈建议使用 QRegularExpression:
| 特性 | QRegExp (旧) | QRegularExpression (新) |
|---|---|---|
| 引擎 | Qt 自定义实现 | **PCRE (Perl Compatible Regular Expressions)** |
| 性能 | 较慢,功能有限 | 快,支持复杂回溯 |
| 标准性 | Qt 独有语法 | 兼容 Perl / Python / JavaScript 语法 |
| 维护状态 | 已废弃 (Deprecated) | 推荐使用 |
结论 :在资源受限的嵌入式平台,正则匹配效率直接影响 UI 响应速度,
QRegularExpression是唯一选择。
2. 核心类结构
主要涉及三个类:
-
QRegularExpression:定义规则(Pattern)。
-
QRegularExpressionMatch:存储单次匹配结果。
-
QRegularExpressionMatchIterator:存储多次匹配结果(全局匹配)。
3. 基础用法:匹配与捕获
3.1 简单匹配
cpp
#include <QRegularExpression>
#include <QDebug>
QString text = "Video Resolution: 1920x1080 @ 60Hz";
QRegularExpression re("(\\d{4})x(\\d{4})");
QRegularExpressionMatch match = re.match(text);
if (match.hasMatch()) {
QString width = match.captured(1); // "1920"
QString height = match.captured(2); // "1080"
}
3.2 捕获组 (Capture Groups)
这是流媒体协议解析中最常用的功能(例如解析 SDP 或 RTSP 头):
-
captured(0):整个匹配的字符串。 -
captured(1):第一个括号里的内容。
4. 高级特性
4.1 贪婪与非贪婪匹配
在处理不定长的数据流(如 JSON 或 XML 片段)时非常重要。
cpp
QString data = "<video>4K</video><audio>AAC</audio>";
// 贪婪匹配(默认):会匹配到最后一个 </xxx>
QRegularExpression greedyRe("<video>.*</video>");
// 非贪婪匹配:只匹配到第一个结束标签
QRegularExpression lazyRe("<video>.*?</video>");
4.2 命名捕获(Named Capturing Groups)
强烈推荐用于协议解析,代码可读性极高,不怕以后正则改顺序。
cpp
QRegularExpression re(
"^(?<type>\\w+)://"
"(?<ip>\\d+\\.\\d+\\.\\d+\\.\\d+):"
"(?<port>\\d+)$"
);
QRegularExpressionMatch match = re.match("rtsp://192.168.1.100:554");
if (match.hasMatch()) {
qDebug() << "Type:" << match.captured("type"); // rtsp
qDebug() << "IP:" << match.captured("ip"); // 192.168.1.100
qDebug() << "Port:" << match.captured("port"); // 554
}
应用场景:解析 RTSP/HTTP/SRT 地址字符串。
5. 全局匹配(Global Matching)
当你需要从一段日志或 NALU 流中提取所有关键信息时使用。
cpp
QString logData = "Pkt:123 Size:1500\nPkt:124 Size:1450";
QRegularExpression re("Pkt:(\\d+) Size:(\\d+)");
QRegularExpressionMatchIterator it = re.globalMatch(logData);
while (it.hasNext()) {
QRegularExpressionMatch match = it.next();
qDebug() << "Packet" << match.captured(1)
<< "Size" << match.captured(2);
}
6. 性能优化(针对嵌入式 Linux)
在嵌入式linux上运行 Qt 应用时,正则表达式是 CPU 密集型操作,需注意以下几点:
6.1 预编译(Optimize)
最重要的一点 :不要在循环里创建 QRegularExpression对象。
cpp
// ❌ 错误示范:每次调用都会重新编译正则
void badParse(QString data) {
QRegularExpression re("pattern"); // 开销大
...
}
// ✅ 正确做法:使用静态变量或成员变量
void goodParse(QString data) {
static const QRegularExpression re("pattern"); // 只编译一次
...
}
6.2 设置匹配选项
cpp
QRegularExpression re("pattern");
re.setPatternOptions(QRegularExpression::DotMatchesEverythingOption |
QRegularExpression::DontCaptureOption); // 不捕获提高效率
7. 在 Qt Widgets / 输入验证中的应用
你可能需要限制用户输入(如 IP 地址、端口号)。
7.1 QLineEdit 输入校验
cpp
QLineEdit *ipInput = new QLineEdit(this);
QRegularExpression ipRegex(
"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}"
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
);
QValidator *validator = new QRegularExpressionValidator(ipRegex, this);
ipInput->setValidator(validator);
总结
-
放弃 QRegExp ,全面使用
QRegularExpression。 -
善用命名捕获,让协议解析代码更易维护。
-
注意性能 ,将
QRegularExpression对象定义为static const或类成员。 -
结合 GStreamer 调试时,用 Regex 过滤 Pipeline 日志非常高效。
