一、正则表达式介绍
正则表达式(Regular Expression,简称 Regex)是一种用于描述文本模式的强大工具。它通过特定的语法规则,定义字符串的匹配模式,常用于文本的搜索、匹配、替换和验证操作。正则表达式在文本处理、数据清洗、表单验证等场景中应用广泛。
1、核心语法规则
以下是正则表达式的常用语法元素:
| 符号 | 含义 |
|---|---|
. |
匹配任意单个字符(除换行符) |
* |
匹配前一个字符零次或多次 |
+ |
匹配前一个字符一次或多次 |
? |
匹配前一个字符零次或一次 |
\d |
匹配数字(等价于 [0-9]) |
\w |
匹配字母、数字或下划线(等价于 [a-zA-Z0-9_]) |
\s |
匹配空白字符(空格、制表符等) |
[abc] |
匹配方括号内的任意一个字符(如 a、b 或 c) |
[^abc] |
匹配不在方括号内的任意字符 |
(abc) |
分组,将多个字符视为一个单元 |
^ |
匹配字符串开头 |
$ |
匹配字符串结尾 |
| |
逻辑或(如 a|b 匹配 a 或 b) |
2、实用示例
假设需要验证一个电话号码格式(如 138-1234-5678),可用以下正则表达式:
^\d{3}-\d{4}-\d{4}$
-
^和$确保匹配整个字符串 -
\d{3}匹配3位数字 -
-匹配连字符
3、常用场景
-
数据提取
从日志中提取IP地址:\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b -
文本替换
将日期格式2023/08/15替换为2023-08-15:
替换为:(\d{4})/(\d{2})/(\d{2})$1-$2-$3 -
表单验证
邮箱格式校验:^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$
4、常用正则表达式
| 用途描述 | 正则表达式 | 示例匹配值 |
|---|---|---|
| 电子邮箱地址 | ^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$ |
user@example.*** |
| 中国大陆手机号 | ^1[3-9]\d{9}$ |
13800138000 |
| 日期格式 (YYYY-MM-DD) | ^\d{4}-\d{2}-\d{2}$ |
2023-08-15 |
| 中文汉字 | ^[\u4e00-\u9fa5]+$ |
你好世界 |
| 身份证号 (15/18位) | ^(\d{15}|\d{17}[\dXx])$ |
11010519900101123X |
| IP地址 | ^\d{1,3}(\.\d{1,3}){3}$ |
192.168.0.1 |
| 强密码 (8-20位含大小写字母、数字、特殊字符) | ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,20}$ |
Passw0rd! |
| 整数(含负数) | ^-?\d+$ |
-42, 100
|
| 特殊字符检测 | [<>"';&\\] |
<script> |
💡 提示:实际使用时建议根据具体场景调整表达式边界(如添加 ^...$ 严格匹配),并使用在线测试工具验证匹配效果。
5、工具推荐
- 在线测试:RegExr
- 代码支持:Python 的
re模块、JavaScript 的RegExp对象
二、 QRegularExpression类详解
QRegularExpression 是 Qt6 中用于处理正则表达式的核心类。它提供了强大且高效的字符串模式匹配功能,遵循 Perl 兼容的正则表达式语法(PCRE)。在 Qt6 中,它替代了旧的 QRegExp 类,并提供了更好的性能、功能完整性和 Unicode 支持。
1、核心功能
- 模式匹配: 检查字符串是否匹配给定的模式。
- 捕获匹配: 提取与正则表达式中定义的子模式(捕获组)匹配的子字符串。
- 全局匹配: 查找字符串中所有出现的匹配项。
-
字符串操作: 支持查找、替换、分割等基于正则表达式的操作(通常结合
QString的相关方法)。
2、基本使用步骤
-
创建正则表达式对象:
QRegularExpression re("pattern");其中
"pattern"是您的正则表达式字符串。 -
进行匹配:
QRegularExpressionMatch match = re.match("subject string");或者
QRegularExpressionMatch match = re.match("subject string", offset, matchType);-
"subject string"是要匹配的目标字符串。 -
offset(可选) 指定开始匹配的起始位置。 -
matchType(可选) 指定匹配选项(如部分匹配、锚定匹配等)。
-
-
检查匹配结果:
if (match.hasMatch()) { // 成功匹配 QString matched = match.captured(0); // 获取整个匹配的字符串 // ... 处理匹配结果 } else { // 未匹配 if (match.hasPartialMatch()) { // 存在部分匹配(如果启用了相关选项) } } -
获取捕获组:
正则表达式中的圆括号()定义捕获组。// 假设模式为 "^(\\d+)-(\\d+)$" (匹配 "123-456") int group1 = match.captured(1).toInt(); // 获取第一个捕获组 "123" int group2 = match.captured(2).toInt(); // 获取第二个捕获组 "456" QString entireMatch = match.captured(0); // 获取整个匹配 "123-456"
3、常用方法
-
bool isValid() const: 检查正则表达式模式语法是否有效。 -
QString errorString() const: 如果无效,获取错误信息。 -
QString pattern() const: 获取当前设置的正则表达式模式。 -
void setPattern(const QString &pattern): 设置新的正则表达式模式。 -
void setPatternOptions(QRegularExpression::PatternOptions options): 设置匹配选项(如忽略大小写CaseInsensitiveOption、多行模式MultilineOption等)。 -
int captureCount() const: 获取捕获组的数量(不包括第 0 组)。 -
QRegularExpressionMatchIterator globalMatch(const QString &subject) const: 获取一个迭代器,用于遍历字符串中所有匹配项。
4、全局匹配示例
查找字符串中所有出现的单词:
QString text = "The quick brown fox jumps over the lazy dog.";
QRegularExpression re("\\b\\w+\\b"); // 匹配单词边界之间的字符
QRegularExpressionMatchIterator i = re.globalMatch(text);
while (i.hasNext()) {
QRegularExpressionMatch match = i.next();
qDebug() << match.captured(0); // 输出: "The", "quick", "brown", ...
}
5、模式选项
可以通过 setPatternOptions 或使用内联标记设置选项:
// 忽略大小写
QRegularExpression re("hello", QRegularExpression::CaseInsensitiveOption);
re.match("Hello"); // 匹配成功
// 内联标记 (?i)
QRegularExpression re("(?i)hello");
re.match("Hello"); // 匹配成功
常用选项:
-
NoPatternOption: 无选项(默认)。 -
CaseInsensitiveOption: 忽略大小写。 -
DotMatchesEverythingOption:.匹配包括换行符在内的任何字符。 -
MultilineOption:^和$匹配每行的开始和结束,而非整个字符串。 -
ExtendedPatternSyntaxOption: 忽略未转义空格和#后的注释。 -
InvertedGreedinessOption: 反转*和+的贪婪性(使其不贪婪)。 -
DontCaptureOption: 非命名捕获组不捕获(仅命名捕获组有效)。 -
UseUnicodePropertiesOption: 使\w,\d等字符类遵循 Unicode 属性。
6、常见用例示例
6.1、验证电子邮件地址 (简化版)
QRegularExpression emailRe("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
QString email = "user@example.***";
if (emailRe.match(email).hasMatch()) {
qDebug() << "Valid email";
} else {
qDebug() << "Invalid email";
}
6.2、提取 URL 协议和域名
QString url = "https://www.example.***/path";
QRegularExpression urlRe("^(https?)://([^/]+)");
QRegularExpressionMatch match = urlRe.match(url);
if (match.hasMatch()) {
QString protocol = match.captured(1); // "http" 或 "https"
QString domain = match.captured(2); // "www.example.***"
}
6.3、替换所有数字
QString text = "Order 123, Item 456";
QRegularExpression digitRe("\\d+");
QString result = text.replace(digitRe, "NUM"); // 结果: "Order NUM, Item NUM"
7、注意事项
- 语法: 确保熟悉 Perl 兼容正则表达式语法。
-
转义: 在 C++ 字符串中,反斜杠
\需要转义为\\(例如,\d应写作"\\d")。 - 性能: 对于非常复杂的模式或极长的字符串,注意性能影响。考虑优化正则表达式或使用其他字符串处理方法。
-
错误处理: 始终检查
isValid()并在无效时查看errorString()。 -
Qt 版本:
QRegularExpression是 Qt5.1 引入的,在 Qt6 中是主要的正则表达式处理类。
三、代码示例
1、效果展示
2、源码分享
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCoreApplication>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QDebug>
#include <QFile>
#include <QRegularExpression>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
// 示例1:基础匹配
QString text = "Qt 6.2 released on 2021-09-30";
QRegularExpression datePattern(R"(\d{4}-\d{2}-\d{2})");
QRegularExpressionMatch match = datePattern.match(text);
if (match.hasMatch()) {
qDebug() << "找到日期:" << match.captured(0); // 输出: "2021-09-30"
}
// 示例1:全局匹配(查找所有)
QString html = "<p>Hello <b>World</b>!</p>";
QRegularExpression tagPattern(R"(<(\w+)>(.*?)</\1>)");
QRegularExpressionMatchIterator it = tagPattern.globalMatch(html);
while (it.hasNext()) {
QRegularExpressionMatch tagMatch = it.next();
qDebug() << "标签:" << tagMatch.captured(1)
<< "内容:" << tagMatch.captured(2);
// 输出:
// 标签: "b" 内容: "World"
// 标签: "p" 内容: "Hello <b>World</b>!"
}
// 示例3:替换操作
QString phone = "Tel: (123) 456-7890";
QRegularExpression phonePattern(R"(\((\d{3})\)\s(\d{3})-(\d{4}))");
QString formatted = phone.replace(phonePattern, R"(\1-\2-\3)");
qDebug() << "格式化电话:" << formatted; // 输出: "Tel: 123-456-7890"
}