Bootstrap

QRegularExpression

QRegularExpression

1. QRegularExpression 概述

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

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

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

应用场景描述示例
验证regex 可以测试子字符串是否满足特定条件,例如检查是否为整数或是否包含空格。^\d+$ 用于验证一个字符串是否只包含数字。
搜索regex 提供了强大的模式匹配功能,能够比简单的子字符串匹配更精确地查找。\bmail\b 用于在文本中查找完整的单词 “mail”。
搜索和替换regex 可以用不同的子字符串替换所有出现的匹配项。&(?!(amp;)) 可用于将所有出现的 & 替换为 &,但排除后面跟着 amp; 的情况。
字符串分割regex 可用于确定拆分字符串的位置,例如按制表符分隔的字符串。\t 可用于按制表符拆分字符串,如 string1\tstring2\tstring3

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

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 = "[email protected]";
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 枚举定义了用于匹配时的选项。

常数描述
QRegularExpression::NoMatchOption未设置匹配选项。
QRegularExpression::AnchorAtOffsetMatchOption匹配限制在传入的偏移量处精确开始,尽管模式字符串不包含锚定字符。此枚举值在 Qt 6.0 中引入。
QRegularExpression::DontCheckSubjectStringMatchOption不检查主题字符串的 UTF-16 有效性。使用此选项时要谨慎,因为无效字符串可能导致崩溃或安全问题。此枚举值在 Qt 5.4 中引入。

10.2 QRegularExpression::MatchType

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

常数描述
QRegularExpression::NormalMatch正常匹配完成。
QRegularExpression::PartialPreferCompleteMatch优先考虑完整匹配,如果没有则报告部分匹配。
QRegularExpression::PartialPreferFirstMatch找到部分匹配则停止,不尝试其他匹配方案。
QRegularExpression::NoMatch没有进行匹配。默认构造的 QRegularExpressionMatchQRegularExpressionMatchIterator 返回此类型。此枚举值在 Qt 5.1 中引入。

10.3 QRegularExpression::PatternOption

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

常数描述
QRegularExpression::NoPatternOption没有设置模式选项。
QRegularExpression::CaseInsensitiveOption模式以不区分大小写的方式与主题字符串匹配。
QRegularExpression::DotMatchesEverythingOption点元字符 (.) 匹配任何字符,包括换行符。
QRegularExpression::MultilineOption脱字符 (^) 和美元 ($) 在任意换行符后和前匹配。
QRegularExpression::ExtendedPatternSyntaxOption增强可读性,忽略未转义的空格和注释。
QRegularExpression::InvertedGreedinessOption量词贪婪性质倒置:使贪婪变惰性,反之亦然。
QRegularExpression::DontCaptureOption未命名捕获组不捕获子字符串;命名捕获组正常工作。
QRegularExpression::UseUnicodePropertiesOption\w、\d 等字符类匹配 Unicode 属性而不仅仅是 ASCII 字符。

10.4 QRegularExpression::WildcardConversionOption

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

常数描述
QRegularExpression::DefaultWildcardConversion没有设置转换选项。
QRegularExpression::UnanchoredWildcardConversion转换不会锚定模式,允许部分匹配。

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.";
}
;