Qt QRegularExpression正则类,10分钟讲清楚

在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. 核心类结构

主要涉及三个类:

  1. QRegularExpression:定义规则(Pattern)。

  2. QRegularExpressionMatch:存储单次匹配结果。

  3. 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);

总结

  1. 放弃 QRegExp ,全面使用 QRegularExpression

  2. 善用命名捕获,让协议解析代码更易维护。

  3. 注意性能 ,将QRegularExpression对象定义为 static const或类成员。

  4. 结合 GStreamer​ 调试时,用 Regex 过滤 Pipeline 日志非常高效。

相关推荐
Quz3 小时前
QML Hello World 入门示例
qt
xcyxiner3 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner4 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner4 天前
DicomViewer (添加模型类)3
qt
xcyxiner5 天前
DicomViewer (目录调整) 2
qt
xcyxiner5 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
桥田智能7 天前
桥田智能 QT-650S:面向白车身焊装的 800kg 重载快换解决方案
开发语言·qt·系统架构
森G7 天前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt
森G7 天前
77、线程池原理和实现------服务器源码解析----云视频服务项目
服务器·c++·qt
森G7 天前
71、打包发布---------打包发布
c++·qt