QRegularExpression
一、描述
QRegularExpression 类使用正则表达式提供模式匹配。
1.1、正则表达式
正则表达式是处理字符串和文本的非常强大的工具。在许多情况下都很有用,例如:
- 验证:正则表达式可以测试子字符串是否符合某些标准。
- 搜索:一个正则表达式提供了比简单的子字符串匹配更强大的模式匹配。
- 搜索和替换:正则表达式可以用不同的子串替换所有出现的子串。
- 字符串拆分:正则表达式可用于识别字符串应在何处拆分。
1.2、介绍
QRegularExpression 实现的正则表达式完全支持 Unicode。一个正则表达式由两部分组成:一个模式字符串和一组改变模式字符串含义的模式选项。
可以通过将字符串传递给 QRegularExpression 构造函数来设置模式字符串:
QRegularExpression re("a pattern");
由于 C++ 文字字符串规则,必须使用另一个反斜杠转义模式字符串中的所有反斜杠:
// 匹配两个数字,后跟一个空格和一个单词
QRegularExpression re("\\d\\d \\w+");
// 匹配反斜杠
QRegularExpression re2("\\\\");
或者,可以使用原始字符串文字,在这种情况下,不需要转义模式中的反斜杠,R"(...)" 之间的所有字符都被视为原始字符。这简化了编写模式:
// 匹配两个数字后跟一个空格和一个单词
QRegularExpression re(R"(\d\d \w+)");
1.3、正常匹配
为了执行匹配,可以简单地调用 match() 函数,传递要匹配的字符串。match() 函数的结果是一个 QRegularExpressionMatch 对象,可用于检查匹配结果。 例如:
// 匹配两个数字后跟一个空格和一个单词
QRegularExpression re("\\d\\d \\w+");
QRegularExpressionMatch match = re.match("abc123 def");
bool hasMatch = match.hasMatch(); // true
如果匹配成功,(隐式)捕获组编号 0 可用于检索与整个模式字符串匹配的子字符串:
QRegularExpression re("\\d\\d \\w+");
QRegularExpressionMatch match = re.match("abc123 def");
if (match.hasMatch())
{
QString matched = match.captured(0); // matched == "23 def"
// ...
}
通过将偏移量作为 match() 函数的参数传递,也可以在字符串内的任意偏移量处开始匹配。 在以下示例中,“12 abc”不匹配,因为匹配从偏移量 1 开始:
QRegularExpression re("\\d\\d \\w+");
QRegularExpressionMatch match = re.match("12 abc 45 def", 1);
if (match.hasMatch())
{
QString matched = match.captured(0); // matched == "45 def"
// ...
}
1.4、提取捕获的子字符串
QRegularExpressionMatch 对象还包含有关由模式字符串中的捕获组捕获的子字符串的信息。 capture() 函数将返回第 n 个捕获组捕获的字符串:
QRegularExpression re("^(\\d\\d)/(\\d\\d)/(\\d\\d\\d\\d)$");
QRegularExpressionMatch match = re.match("08/12/1985");
if (match.hasMatch())
{
QString day = match.captured(1); // day == "08"
QString month = match.captured(2); // month == "12"
QString year = match.captured(3); // year == "1985"
// ...
}
模式字符串中的捕获组从 1 开始编号,隐式捕获组 0 用于捕获与整个模式匹配的子字符串。
通过使用 captureStart() 和 captureEnd() 函数,还可以检索每个捕获的子字符串的开始和结束偏移量:
QRegularExpression re("abc(\\d+)def");
QRegularExpressionMatch match = re.match("XYZabc123defXYZ");
if (match.hasMatch())
{
int startOffset = match.capturedStart(1); // startOffset == 6
int endOffset = match.capturedEnd(1); // endOffset == 9
// ...
}
所有这些函数都有一个以 QString 作为参数的重载,以便提取命名的捕获子字符串。 例如:
QRegularExpression re("^(?<date>\\d\\d)/(?<month>\\d\\d)/(?<year>\\d\\d\\d\\d)$");
QRegularExpressionMatch match = re.match("08/12/1985");
if (match.hasMatch())
{
QString date = match.captured("date"); // date == "08"
QString month = match.captured("month"); // month == "12"
QString year = match.captured("year"); // year == 1985
}
1.5、全部匹配
全部匹配对于在字符串中查找给定正则表达式的所有匹配项很有用。
globalMatch() 返回一个 QRegularExpressionMatchIterator,它是一个类似于 Java 的前向迭代器,可用于迭代结果。例如:
QRegularExpression re("(\\w+)");
QRegularExpressionMatchIterator i = re.globalMatch("the quick fox");
QStringList words;
while (i.hasNext())
{
QRegularExpressionMatch match = i.next();
QString word = match.captured(1);
words << word;
}
// words 包含 "the", "quick", "fox"
也可以在基于范围的 for 循环中简单地使用 globalMatch() 的结果:
QRegularExpression re(R"(\w+)");
QString subject("the quick fox");
for (const QRegularExpressionMatch &match : re.globalMatch(subject))
{
// ...
}
1.6、部分匹配
部分匹配通常比正常匹配效率低得多,因为无法使用匹配算法的许多优化。
在调用 match() 或 globalMatch() 时,必须通过指定 PartialPreferCompleteMatch 或 PartialPreferFirstMatch 的匹配类型来显式请求部分匹配。如果找到部分匹配,则在 match() 返回的 QRegularExpressionMatch 对象上调用 hasMatch() 函数将返回 false,但 hasPartialMatch() 将返回 true。
二、类型成员
1、enum QRegularExpression::MatchOption:匹配选项
- NoMatchOption:未设置匹配选项。
- AnchoredMatchOption:等于 AnchorAtOffsetMatchOption。
- AnchorAtOffsetMatchOption:匹配被限制在传递给 match() 的偏移量处才能成功。请注意,传递此选项不会将匹配的结尾锚定到字符串的结尾,如果要完全锚定正则表达式,使用 anchoredPattern()。
- DontCheckSubjectStringMatchOption:在尝试匹配之前未检查字符串的 UTF-16 有效性。使用此选项时要格外小心,因为尝试匹配无效字符串可能会使程序崩溃和/或构成安全问题。
2、enum QRegularExpression::MatchType:此枚举定义了应该针对字符串尝试的匹配类型。
- NormalMatch:正常匹配。
- PartialPreferCompleteMatch:部分匹配。如果找到部分匹配,则将其记录下来,并尝试其他匹配的替代方案。如果找到完全匹配,则优先于部分匹配;在这种情况下,只报告完整的匹配。相反,如果没有找到完全匹配(但只有部分匹配),则报告部分匹配。
- PartialPreferFirstMatch:部分匹配。如果找到部分匹配,则匹配停止并报告部分匹配。
- NoMatch:不匹配。
3、enum QRegularExpression::PatternOption:此枚举定义了模式字符串应该被解释的方式的修饰符,因此模式匹配主题字符串的方式。
- NoPatternOption:未设置模式选项。
- CaseInsensitiveOption:模式应该以不区分大小写的方式匹配主题字符串。
- DotMatchesEverythingOption:模式字符串中的点元字符 (.) 允许匹配主题字符串中的任何字符,包括换行符(通常点不匹配换行符)。
- MultilineOption:模式字符串中的脱字符 (^) 和美元 ($) 元字符被允许分别在主题字符串中的任何换行符之后和之前以及开头和结尾处匹配主题字符串的最后。
- ExtendedPatternSyntaxOption:模式字符串中未转义且在字符类之外的任何空格都将被忽略。此外,字符类之外的未转义的 (#) 会导致所有后续字符,直到第一个换行符(包括)被忽略。这可以用来增加模式字符串的可读性以及在正则表达式中添加注释;如果模式字符串是从文件加载或由用户编写的,这特别有用,因为在 C++ 代码中,始终可以使用字符串文字的规则将注释放在模式字符串之外。
- InvertedGreedinessOption:量词的贪心是倒置的:*、+、?、{m,n} 等变得懒惰,而它们的懒惰版本 (*?, +?, ??, {m,n}?等)变得贪婪。
- DontCaptureOption:未命名的捕获组不捕获子字符串;命名的捕获组仍然按预期工作,以及对应于整个匹配的隐式捕获组编号 0。
- UseUnicodePropertiesOption:\w、\d等字符类的含义,以及它们对应的含义(\W、\D等),从只匹配ASCII字符变为匹配任何具有相应 Unicode 属性的字符。
4、enum QRegularExpression::WildcardConversionOption:此枚举定义了将通配符 glob 模式转换为正则表达式模式的方式的修饰符。
- DefaultWildcardConversion:未设置转换选项。
- UnanchoredWildcardConversion:转换不会锚定模式。这允许通配符表达式的部分字符串匹配。
三、成员函数
1、【static】QString anchoredPattern(QStringView expression)
返回包装在 \A 和 \z 锚点之间的表达式,以用于精确匹配。
2、int captureCount()
返回模式字符串中捕获组的数量,如果正则表达式无效,则返回 -1。
注意:返回的数字中不包含隐式捕获组 0。
3、QString errorString()
返回检查正则表达式有效性时发现的错误的文本描述。
4、【static】QString escape(QStringView str)
转义 str 的所有字符,使它们在用作正则表达式模式字符串时不再具有任何特殊含义,并返回转义后的字符串。
例如:
QString escaped = QRegularExpression::escape("a(x) = f(x) + g(x)");
// escaped == "a\\(x\\)\\ \\=\\ f\\(x\\)\\ \\+\\ g\\(x\\)"
这对于从任意字符串构建模式非常方便:
QString pattern = "(" + QRegularExpression::escape(name) +
"|" + QRegularExpression::escape(nickname) + ")";
QRegularExpression re(pattern);
5、QRegularExpression fromWildcard(QStringView pattern, Qt::CaseSensitivity cs = Qt::CaseInsensitive, QRegularExpression::WildcardConversionOptions options = DefaultWildcardConversion)
返回 glob 模式的正则表达式。如果 cs 为 Qt::CaseSensitive,则正则表达式将区分大小写,并根据选项进行转换。
6、QRegularExpressionMatchIterator globalMatch(const QString &subject, qsizetype offset = 0, QRegularExpression::MatchType matchType = NormalMatch, QRegularExpression::MatchOptions matchOptions = NoMatchOption)
尝试对给定的主题字符串执行正则表达式的全局匹配,从 offset 位置开始,使用 matchType 类型的匹配并遵守给定的 matchOptions。
返回的 QRegularExpressionMatchIterator 位于第一个匹配结果(如果有)之前。
7、QRegularExpressionMatch match(const QString &subject, qsizetype offset = 0, QRegularExpression::MatchType matchType = NormalMatch, QRegularExpression::MatchOptions matchOptions = NoMatchOption) const
尝试将正则表达式与给定的主题字符串匹配,从 offset 位置开始,使用 matchType 类型的匹配并遵守给定的 matchOptions。
返回的 QRegularExpressionMatch 对象包含匹配的结果。
8、bool isValid()
如果正则表达式是有效的正则表达式(即它不包含语法错误等),则返回 true,否则返回 false。 使用 errorString() 获取错误的文本描述。
9、QStringList namedCaptureGroups()
返回 captureCount() + 1 个元素的列表,其中包含模式字符串中命名的捕获组的名称。对列表进行排序,使得列表中位置 i 的元素是第 i 个捕获组的名称(如果它有名称),或者如果该捕获组未命名,则为空字符串。
例如,给定正则表达式:
(?<day>\d\d)-(?<month>\d\d)-(?<year>\d\d\d\d) (\w+) (?<name>\w+)
namedCaptureGroups() 将返回以下列表:
("", "day", "month", "year", "", "name")
这对应于捕获组#0(对应于整个匹配)没有名称,捕获组#1 的名称为“day”,捕获组#2 的名称为“month”,等等。
10、QString pattern() / void setPattern(const QString &pattern)
正则表达式的模式字符串。
11、qsizetype patternErrorOffset()
返回在检查正则表达式的有效性时发现错误的模式字符串内的偏移量。如果没有发现错误,则返回 -1。
12、QRegularExpression::PatternOptions patternOptions() /
void setPatternOptions(QRegularExpression::PatternOptions options)
正则表达式的模式选项。
13、【static】QString wildcardToRegularExpression(QStringView pattern, QRegularExpression::WildcardConversionOptions options = DefaultWildcardConversion)
返回给定 glob 模式的正则表达式表示。
默认情况下,返回的正则表达式是完全锚定的。即不需要对结果再次调用 anchoredPattern()。要获取未锚定的正则表达式,使用 UnanchoredWildcardConversion 作为转换选项传递。
此实现严格遵循 glob 模式的通配符定义:
- c:除了下面提到的那些之外,任何字符都代表它自己。因此 c 匹配字符 c。
- ?:匹配任何单个字符。它与 相同。在完整的正则表达式中。
- *:匹配零个或多个任意字符。它与完整正则表达式中的 .* 相同。
- [abc]:匹配括号中的一个字符。
- [a-c]:匹配括号中给定范围内的一个字符。
- [!abc]:匹配括号中未给出的一个字符。它与完整正则表达式中的 [^abc] 相同。
- [!a-c]:匹配一个不在括号中给定范围内的字符。它与完整正则表达式中的 [^a-c] 相同。
QRegularExpressionMatch
一、描述
QRegularExpressionMatch 类提供将 QRegularExpression 与字符串匹配的结果。
可以通过调用 QRegularExpression::match() 函数来获得 QRegularExpressionMatch 对象。
此外,QRegularExpressionMatch 返回模式字符串中捕获组捕获的子字符串。索引为 0 的隐式捕获组捕获整个匹配的结果。capture() 函数返回通过捕获组的索引或其名称捕获的每个子字符串:
QRegularExpression re("(\\d\\d) (?<name>\\w+)");
QRegularExpressionMatch match = re.match("23 Jordan");
if (match.hasMatch())
{
QString number = match.captured(1); // first == "23"
QString name = match.captured("name"); // name == "Jordan"
}
二、成员函数
1、bool hasCaptured(const QString &name)
如果名为 name 的捕获组在主题字符串中捕获了某些内容,则返回 true,否则返回 false(或者如果没有名为 name 的捕获组)。
bool hasCaptured(int nth)
如果第 n 个捕获组捕获了主题字符串中的某些内容,则返回 true,否则返回 false(或者如果没有这样的捕获组)。
注意:隐式捕获组号 0 捕获整个模式匹配的子字符串。
2、bool hasMatch()
正则表达式与主题字符串是否匹配。
bool hasPartialMatch()
正则表达式与主题字符串是否部分匹配。
注意:只有明确使用其中一种部分匹配类型的匹配才能产生部分匹配。尽管如此,如果这样的匹配完全成功,此函数将返回 false,而 hasMatch() 将返回 true。
3、QString captured(int nth = 0)
返回第 n 个捕获组捕获的子字符串。
注意:隐式捕获组号 0 捕获整个模式匹配的子字符串。
QString captured(const QString &name)
返回名为 name 的捕获组捕获的子字符串。
4、qsizetype capturedEnd(int nth = 0)
返回第 n 个捕获组捕获的子字符串结束位置之后的主题字符串内的偏移量。如果第 n 个捕获组未捕获字符串或不存在,则返回 -1。
qsizetype capturedEnd(const QString &name)
在名为 name 的捕获组捕获的子字符串的结束位置之后立即返回主题字符串内的偏移量。
5、qsizetype capturedLength(int nth = 0)
返回第 n 个捕获组捕获的子字符串的长度。
qsizetype capturedLength(const QString &name)
返回名为 name 的捕获组捕获的子字符串的长度。
6、qsizetype capturedStart(int nth = 0)
返回主题字符串内对应于第 n 个捕获组捕获的子字符串的起始位置的偏移量。
qsizetype capturedStart(const QString &name)
返回主题字符串内的偏移量,该偏移量对应于名为 name 的捕获组捕获的子字符串的起始位置。
7、QStringList capturedTexts()
返回由捕获组捕获的所有字符串的列表,按照组本身出现在模式字符串中的顺序。该列表包括隐式捕获组编号 0,捕获与整个模式匹配的子字符串。
QRegularExpression rx("\\d+");//数字
QString str = "string96";
QRegularExpressionMatch match = rx.match(str);
qDebug()<<match.hasMatch()<<match.capturedTexts();
8、QStringView capturedView(int nth = 0)
返回第 n 个捕获组捕获的子字符串的视图。
注意:隐式捕获组号 0 捕获整个模式匹配的子字符串。
QStringView capturedView(QStringView name)
返回由名为 name 的捕获组捕获的字符串的视图。
9、bool isValid()
匹配对象是否作为对有效 QRegularExpression 对象调用的 QRegularExpression::match() 函数的结果获得的。
10、int lastCapturedIndex()
返回最后一个捕获组的索引,包括隐式捕获组 0。
这可用于提取所有捕获的子字符串:
QRegularExpressionMatch match = re.match(string);
for (int i = 0; i <= match.lastCapturedIndex(); ++i)
{
QString captured = match.captured(i);
// ...
}
QRegularExpressionMatchIterator
一、描述
QRegularExpressionMatchIterator 类为 QRegularExpression 对象与字符串的全局匹配结果提供了一个迭代器。
QRegularExpressionMatchIterator 对象是一个仅向前的类似 Java 的迭代器,可以通过调用 QRegularExpression::globalMatch() 函数获得。
每个结果都是一个 QRegularExpressionMatch 对象,其中包含该结果的所有信息(包括捕获的子字符串)。
例如:
QRegularExpression re("(\\w+)");
QString subject("the quick fox");
QRegularExpressionMatchIterator it = re.globalMatch(subject);
while (it.hasNext())
{
QRegularExpressionMatch match = it.next();
// ...
}
此外,也提供了一个 peekNext() 函数来获取下一个结果,而无需推进迭代器。
也可以在基于范围的 for 循环中简单地使用 QRegularExpression::globalMatch() 的结果,例如:
QRegularExpression re(R"(\w+)");
QString subject("the quick fox");
for (const QRegularExpressionMatch &match : re.globalMatch(subject))
{
// ...
}
二、成员函数
1、bool hasNext()
如果迭代器前面至少有一个匹配结果,则返回 true;否则返回false。
2、bool isValid()
迭代器对象是否作为对有效 QRegularExpression 对象调用的 QRegularExpression::globalMatch() 函数的结果获得的。
3、QRegularExpressionMatch next()
返回下一个匹配结果并将迭代器前进一个位置。
注意:当迭代器位于结果集的末尾时调用此函数会导致未定义的结果。
4、QRegularExpressionMatch peekNext()
在不移动迭代器的情况下返回下一个匹配结果。
注意:当迭代器位于结果集的末尾时调用此函数会导致未定义的结果。