在 C++ Qt 项目中,你可以使用 QRegularExpression
类结合正则表达式来匹配 QString
中的内容。下面介绍如何使用正则表达式进行匹配、提取和替换操作。
一、基本用法:创建正则表达式对象
cpp
#include <QRegularExpression>
QString m_buffer = "Hello, 2025! Today is 2025-05-30.";
// 创建正则表达式对象(匹配四位数字)
QRegularExpression re("\\d{4}");
二、常见匹配操作
1. 检查是否匹配
cpp
// 检查整个字符串是否匹配
bool isExactMatch = re.match(m_buffer).hasMatch();
// 检查字符串中是否包含匹配项
bool containsMatch = m_buffer.contains(re);
2. 查找第一个匹配项
cpp
QRegularExpressionMatch match = re.match(m_buffer);
if (match.hasMatch()) {
QString matchedText = match.captured(0); // 整个匹配的文本
int pos = match.capturedStart(0); // 匹配的起始位置
int length = match.capturedLength(0); // 匹配的长度
}
3. 查找所有匹配项
cpp
QRegularExpressionMatchIterator it = re.globalMatch(m_buffer);
while (it.hasNext()) {
QRegularExpressionMatch match = it.next();
QString matchedText = match.captured(0);
// 处理每个匹配项
}
4. 使用捕获组提取子字符串
cpp
// 匹配日期格式:YYYY-MM-DD
QRegularExpression dateRe("(\\d{4})-(\\d{2})-(\\d{2})");
QRegularExpressionMatch match = dateRe.match(m_buffer);
if (match.hasMatch()) {
QString fullDate = match.captured(0); // 完整匹配:2025-05-30
QString year = match.captured(1); // 第一组:2025
QString month = match.captured(2); // 第二组:05
QString day = match.captured(3); // 第三组:30
}
三、高级用法
1. 设置匹配选项
cpp
// 不区分大小写
QRegularExpression re("hello", QRegularExpression::CaseInsensitiveOption);
// 多行模式(^ 和 $ 匹配行的开始和结束)
QRegularExpression multiLineRe("^\\d+", QRegularExpression::MultilineOption);
2. 替换匹配内容
cpp
// 将所有数字替换为 "X"
QString result = m_buffer.replace(re, "X");
// 结果:"Hello, X! Today is X-X-X."
// 使用捕获组替换
QString replaced = m_buffer.replace(dateRe, "\\1年\\2月\\3日");
// 结果:"Hello, 2025! Today is 2025年05月30日."
3. 分割字符串
cpp
// 按逗号或空格分割字符串
QRegularExpression splitRe("[,\\s]+");
QStringList parts = m_buffer.split(splitRe);
四、在你的项目中应用正则表达式
假设你需要从 dbus-monitor
的输出中提取 time=
后面的时间戳:
cpp
QString m_buffer = "method call time=1748411906.768461 sender=:1.100 ...";
// 正则表达式:匹配 "time=" 后跟数字和小数点
QRegularExpression timeRe("time=(\\d+\\.\\d+)");
QRegularExpressionMatch match = timeRe.match(m_buffer);
if (match.hasMatch()) {
QString timestampStr = match.captured(1); // 提取时间戳:1748411906.768461
double timestamp = timestampStr.toDouble();
}
五、正则表达式语法参考
符号 | 含义 | 示例 |
---|---|---|
^ |
匹配字符串开始 | ^hello |
$ |
匹配字符串结束 | world$ |
. |
匹配任意字符(除换行符) | h.t |
* |
匹配前一个字符 0 次或多次 | he*llo |
+ |
匹配前一个字符 1 次或多次 | he+llo |
? |
匹配前一个字符 0 次或 1 次 | colou?r |
{n} |
匹配前一个字符 n 次 | a{3} |
{n,} |
匹配前一个字符至少 n 次 | a{3,} |
{n,m} |
匹配前一个字符 n 到 m 次 | a{3,5} |
[ ] |
匹配方括号中的任意字符 | [aeiou] |
[^ ] |
匹配不在方括号中的任意字符 | [^aeiou] |
( ) |
分组,用于捕获子字符串 | (\\d{2})-(\\d{2}) |
` | ` | 或操作 |
\d |
匹配数字(等价于 [0-9] ) |
\d{3} |
\D |
匹配非数字(等价于 [^0-9] ) |
\D+ |
\s |
匹配空白字符 | \s+ |
\S |
匹配非空白字符 | \S+ |
\w |
匹配单词字符(字母、数字、下划线) | \w+ |
\W |
匹配非单词字符 | \W+ |
六、性能注意事项
- 预编译正则表达式:对于频繁使用的正则表达式,建议创建为类成员变量,避免重复编译。
- 使用简单模式:复杂的正则表达式会显著影响性能,尽量简化。
- 检查匹配位置 :使用
match.capturedStart()
确定匹配位置,避免重复查找。