QRegularExpression

1. QRegularExpression 概述

QRegularExpression 是 Qt 5.10 引入的类,用于处理正则表达式。它提供了更现代和高效的正则表达式功能,支持 Perl 兼容的正则表达式(PCRE),与之前的 QRegExp 相比,性能和功能都得到增强。

正则表达式30分钟入门教程

正则表达式(regex)是处理字符串和文本的强大工具,广泛应用于各种场景。以下是一些常见的用法:

关于正则表达式的好参考包括:

2. 基本用法

2.1 创建正则表达式对象

#include <QRegularExpression>
#include <QString>
#include <QDebug>

int main() 
{
    QString pattern = R"(\d+)"; // 匹配一个或多个数字
    QRegularExpression regex(pattern);

    if (!regex.isValid()) 
    {
        qDebug() << "Invalid regular expression!";
    }

    return 0;
}

2.2 匹配字符串

使用 match 方法进行单次匹配:

QString text = "The number is 12345.";
QRegularExpressionMatch match = regex.match(text);

if (match.hasMatch()) 
{
    qDebug() << "Match found:" << match.captured(0); // 捕获整个匹配
} 
else 
{
    qDebug() << "No match found.";
}

2.3 查找所有匹配项

使用 globalMatch 查找所有匹配项:

QString text = "Numbers: 123, 456, 789.";
QRegularExpressionMatchIterator it = regex.globalMatch(text);

while (it.hasNext()) 
{
    QRegularExpressionMatch match = it.next();
    qDebug() << "Match found:" << match.captured(0);
}

2.4 使用捕获组

正则表达式可以包含捕获组,用于提取子模式:

QString pattern = R"(\d+)-(\w+)"; // 匹配数字-字母组合
QRegularExpression regex(pattern);
QString text = "Order number is 1234-ABCD.";

QRegularExpressionMatch match = regex.match(text);
if (match.hasMatch()) 
{
    qDebug() << "Full match:" << match.captured(0); // 整个匹配
    qDebug() << "First group:" << match.captured(1); // 第一个捕获组
    qDebug() << "Second group:" << match.captured(2); // 第二个捕获组
}

2.5 替换字符串

使用 QString::replace 方法与正则表达式结合,可以进行替换操作:

QString pattern = R"(\d+)"; // 匹配一个或多个数字
QRegularExpression regex(pattern);

QString text = "Replace 123 with XYZ.";
QString replacedText = text.replace(regex, "XYZ");

qDebug() << "Original text:" << text;
qDebug() << "Replaced text:" << replacedText; // 输出: "Replace XYZ with XYZ."

3. 正则表达式常见操作

  • 匹配:使用 match() 方法。
  • 查找:使用 globalMatch() 方法获取所有匹配项。
  • 替换:使用 QString::replace() 方法结合正则表达式。
  • 捕获组:使用括号 () 来定义捕获组,通过 captured() 方法访问。

4. 进阶功能

  • 模式修饰符:可以使用模式修饰符来改变匹配行为,例如忽略大小写。

    QRegularExpression regex("pattern", QRegularExpression::CaseInsensitiveOption);
    
  • 支持 UnicodeQRegularExpression 自然支持 Unicode 字符集。

5. 字符串匹配和替换示例

以下是一个完整的示例,展示了如何使用 QRegularExpression 进行字符串匹配和替换:

#include <QCoreApplication>
#include <QRegularExpression>
#include <QString>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString pattern = R"(\d+)"; // 匹配数字
    QRegularExpression regex(pattern);

    QString text = "Extract numbers: 42 and 1001.";

    // 匹配和提取
    QRegularExpressionMatchIterator it = regex.globalMatch(text);
    while (it.hasNext())
    {
        QRegularExpressionMatch match = it.next();
        qDebug() << "Match found:" << match.captured(0);
    }

    // 替换
    QString replacedText = text.replace(regex, "NUMBER");
    qDebug() << "Replaced text:" << replacedText;

    return a.exec();
}

6. 性能优化

虽然 QRegularExpression 提供了强大的功能,但在处理复杂正则表达式或大文本时,性能可能成为一个问题。以下是一些优化建议:

  • 编译正则表达式:如果一个正则表达式需要多次使用,可以考虑将其编译为 QRegularExpression 对象,避免重复编译。

    QRegularExpression regex("your_pattern");
    
  • 限制匹配范围:尽量减少待匹配文本的范围。例如,可以先进行简单的字符串搜索,确定是否有必要执行复杂的正则表达式匹配。

7. 错误处理

QRegularExpression 提供了错误处理机制,以便在正则表达式无效时获取详细信息。可以使用 errorString() 方法获取错误信息。

QString invalidPattern = "[";
QRegularExpression regex(invalidPattern);
if (!regex.isValid())
{
    qDebug() << "Error:" << regex.errorString();
}

8. 常见正则表达式模式

以下是一些常见的正则表达式模式:

  • 匹配邮箱地址

    R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})"
    
  • 匹配URL

    R"((https?://[^\s/$.?#].[^\s]*)"
    
  • 匹配电话号码(简单示例,可能需要根据实际情况调整):

    R"(\+?\d{1,3}[- ]?\(?\d{1,4}?\)?[- ]?\d{1,4}[- ]?\d{1,9})"
    

9. 实际应用示例

以下是一些实际应用场景,展示了如何使用 QRegularExpression 处理不同类型的文本数据。

9.1 验证输入格式

假设你需要验证用户输入的邮箱格式:

QString email = "example@domain.com";
QRegularExpression emailRegex(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");

if (emailRegex.match(email).hasMatch()) 
{
    qDebug() << "Valid email format.";
} 
else
{
    qDebug() << "Invalid email format.";
}

9.2 从文本中提取信息

假设你需要从日志文件中提取时间戳和错误信息:

QString logData = "2023-10-01 12:34:56 ERROR Something went wrong.";
QRegularExpression logRegex(R"((\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (ERROR|WARNING|INFO) (.+))");

QRegularExpressionMatch match = logRegex.match(logData);
if (match.hasMatch()) 
{
    qDebug() << "Timestamp:" << match.captured(1);
    qDebug() << "Log Level:" << match.captured(2);
    qDebug() << "Message:" << match.captured(3);
}

9.3 替换敏感词

假设你需要过滤用户评论中的敏感词:

QString comment = "This is a bad and ugly comment.";
QString sensitiveWords = R"(bad|ugly)"; // 可以根据需求添加更多词汇
QRegularExpression regex(sensitiveWords);

QString filteredComment = comment.replace(regex, "***");
qDebug() << "Filtered comment:" << filteredComment;

10. QRegularExpression 文档概述

下面是关于 QRegularExpression 相关类和枚举的详细说明,包括其成员类型和用法介绍。

10.1 QRegularExpression::MatchOptions

MatchOptions 枚举定义了用于匹配时的选项。

10.2 QRegularExpression::MatchType

MatchType 枚举定义了匹配类型的选项。

10.3 QRegularExpression::PatternOption

PatternOption 枚举定义了正则表达式模式的选项。

10.4 QRegularExpression::WildcardConversionOption

WildcardConversionOption 枚举定义了将通配符模式转换为正则表达式模式的方式。

10.5 QRegularExpressionMatch

QRegularExpressionMatch 类表示正则表达式的匹配结果,提供了匹配信息获取的方法,如捕获的子字符串和匹配位置等。

示例代码

QString text = "Example: 12345";
QRegularExpression regex(R"(\d+)");
QRegularExpressionMatch match = regex.match(text);

if (match.hasMatch()) 
{
    qDebug() << "Matched value:" << match.captured(0); // 输出捕获的数字
    qDebug() << "Start position:" << match.capturedStart(0);
    qDebug() << "End position:" << match.capturedEnd(0);
}

10.6 QRegularExpressionMatchIterator

QRegularExpressionMatchIterator 用于迭代多个匹配结果。可以通过 globalMatch() 方法获取所有匹配。

示例代码

QString text = "Numbers: 123, 456, 789";
QRegularExpression regex(R"(\d+)");
QRegularExpressionMatchIterator it = regex.globalMatch(text);

while (it.hasNext()) 
{
    QRegularExpressionMatch match = it.next();
    qDebug() << "Found:" << match.captured(0);
}

10.7 QRegularExpressionValidator

QRegularExpressionValidator 使用正则表达式来验证输入字符串的有效性。它可以判断输入是否接受、处于中间状态或无效。

示例代码

#include <QRegularExpressionValidator>
#include <QString>

QString pattern = "[A-Z][0-9]"; // 示例正则表达式
QRegularExpressionValidator validator(QRegularExpression(pattern));

QString input = "A1";
int pos = 0; // 输入位置
if (validator.validate(input, pos) == QValidator::Acceptable) 
{
    qDebug() << "Input is valid.";
} 
else
{
    qDebug() << "Input is invalid.";
}
09-29 20:16