正则表达式(regular expression)————以Qt为例

1 应用

  • 1验证:测试一个子字符串是否是符合一些规范。(例如:是否是一个整数或者不包含任何空格)
  • 2 搜索:提供了比简单的子字符串匹配更加强大的匹配模式。(例如,匹配单词mail或者letter,而不匹配email、mailman或者letterbox)
  • 3 查找或替换:使用一个不同的字符串替换所有的匹配的子字符串(例如使用Mail替换一个字符串中所有的M字符)
  • 4 字符串分割:可以识别在那里进行字符串分割。例如,分割制表符隔离的字符串。

Qt中的QRegExp类实现了使用正则表达式进行模式匹配。QRegExp是以Perl的正则表达式语言为蓝本,它可以完全支持Unocode。QRegExp中的愈发规则可以使用setPatternSyntax函数来更改。

2 简介

2.1 组成

一个正则表达式由表达式(expressions)、量词(quantifiers)和断言(assertions)组成。

表达式:

  • 一个简答的表达式就是一个字符。
    • 例如:x和5。
  • 一组字符可以使用方括号括起来。
    • 例如:[ABC]会匹配A、B、C,也可以简写为[A-C]。

量词:

  • 必须要匹配表达式出现的次数。
    • x{1,1}意味着必须匹配且只能匹配一个字符;
    • x{1,5}意味着匹配一列字符x,其中至少包含一个字符x,但是最多包含5个字符x。

例如使用regexp匹配0~99之间的整数,

  • 因为一个数最多出现次数为2,因此可以写为[0-9]{1,2}

但是这样写会匹配出现在字符串中间的整数,如果想匹配的整数是整个字符串,那么需要使用断言"^“和”$"

断言:

  • 当^在regexp中作为第一个字符串时,意味着regexp必须从字符串的开始进行匹配;
  • 当$在regexp中作为 最后一个字符串时,意味着regexp必须匹配到字符串的结尾。
    例如,匹配0~99,^[0,9]{1,2}$

2.2 特殊字符

使用特殊符号表示一些常见的字符组和量词。

  • 例如[0,9]使用\d来代替;
  • 对于只出现一次的量词{1,1},可以使用表达式本身代替,例如:x{1,1}等价于x
  • 要匹配0~99可以写为^d{1,2}$或者^\d\d{0,1},{0,1}表示字符是可选的,就是只出现一次或者不出现,它可以使用?来代替,这样就变为^\d\d?$

2.2.1 匹配多个字符串

例如要匹配"mail"和"letter"其中的一个,但是不要匹配那些包含这些单词的量词,比如"email"和“letterbox”。
要匹配“mail“,可以写为m{1,1}a{1,1}i{1,1}l{1,1}或者是mail.
使用"|"来包含另外一个单词,所以结果为(mail|letter)

为了强制匹配的开始和结束都在单词的边界上,使要将regexp包含在\b单词边界断言中,即\b(mail|letter)\b.
\b断言在regexp中匹配一个位置,一个单词的边界是任何的非单词字符,如空格、新行或者一个字符串的开始或者结束。

2.2.2 替换字符串

如果像使用"Mail"替换一个字符串中的字符M,但是字符M的后面是"ail"的话就不再替换,可以使用(?!E)断言。例如这里regexp应该写成M(?!Mail)

2.2.3 统计字符出现次数

如果想统计"Eric"和“Eirik”在字符串中出现的次数,可以使用\b(Eric|Eriik)\b\bEi?ri[ck]\b

2.3 Qt中使用

由于"“是转义字符,因此使用”\d"时,要写成"\d";如果需要""本身,需要写成“\\”.

QRegexp中的indexIn()函数:从指定位置开始向后对字符串进行匹配,默认是从字符串开始匹配。
如果匹配成功是,返回第一个匹配到的位置的索引,
如果没有匹配到则返回-1。

setPattern()函数用来输入一个regexp。

QString的replace函数可以使用给定的regexp和替换字符来进行字符串的替换。

 QRegExp rx("^\\d\\d?$");           // 两个字符都必须为数字,第二个字符可以没有
    qDebug() << rx.indexIn("a1");            // 结果为-1,不是数字开头
    qDebug() << rx.indexIn("5");             // 结果为0
    qDebug() << rx.indexIn("5b");            // 结果为-1,第二个字符不是数字
    qDebug() << rx.indexIn("12");            // 结果为0
    qDebug() << rx.indexIn("123");           // 结果为-1,超过了两个字符
    qDebug() << "*******************";       // 输出分割符,为了显示清晰
    rx.setPattern("\\b(mail|letter)\\b");    // 匹配mail或者letter单词
    qDebug() << rx.indexIn("emailletter");   // 结果为-1,mail不是一个单词
    qDebug() << rx.indexIn("my mail");       // 返回3
    qDebug() << rx.indexIn("my email letter"); // 返回9
    qDebug() << "*******************";
    rx.setPattern("M(?!ail)");               // 匹配字符M,其后面不能跟有ail字符
    QString str1 = "this is M";
    str1.replace(rx, "Mail");                // 使用"Mail"替换匹配到的字符
    qDebug() << "str1: " << str1;            // 结果为this is Mail
    QString str2 = "my M,your Ms,his Mail";
    str2.replace(rx,"Mail");
    qDebug() << "str2: " << str2;            // 结果为my Mail,your Mails,his Mail
    qDebug() << "*******************";
    QString str3 = "One Eric another Eirik, and an Ericsson. "
                   "How many Eiriks, Eric?"; // 一个字符串如果一行写不完,换行后两行都需要加双引号
    QRegExp rx2("\\bEi?ri[ck]\\b");         // 匹配Eric或者Eirik
    int pos = 0;
    int count = 0;
    while (pos >= 0) {
        pos = rx2.indexIn(str3, pos);
        if (pos >= 0) {
            ++pos;                         // 从匹配的字符的下一个字符开始匹配
            ++count;                       // 匹配到的数目加1
        }
    }

3 regexp结构集合

3.1 表达式

在这里插入图片描述
在这里插入图片描述
^在方括号中表示相反的意思,[^abc]表示匹配任何字符除了abc。

-表示范围,[W-Z]表示WYZ中的其中一个。

3.2 量词

在这里插入图片描述
量词一般都会尽可能多的去匹配,如0+匹配2005时,会匹配3个零,如果想只匹配一个使用setMinimal(true)设置。

3.3 断言

在这里插入图片描述

3.4 通配符

在这里插入图片描述
QRegExp使用setPatternSyntax()来在通配符和regexp切换。
在这里插入图片描述

4 文本捕获

使用括号对一些元素组合在一起,这样既可以对它们进行量化,也可以捕获它们。
使用cap()和capturedTexts()函数来提取匹配字符。

    QRegExp rx3("*.txt");
    rx3.setPatternSyntax(QRegExp::Wildcard);
    qDebug() << rx3.exactMatch("README.txt");        // 结果为true
    qDebug() << rx3.exactMatch("welcome.txt.bak");   // 结果为false

    QRegExp rx4("(\\d+)");
    QString str4 = "Offsets: 12 14 99 231 7";
    QStringList list;
    int pos2 = 0;
    while ((pos2 = rx4.indexIn(str4, pos2)) != -1) {
        list << rx4.cap(1);                      // 第一个捕获到的文本
        pos2 += rx4.matchedLength();             // 上一个匹配的字符串的长度
    }
    qDebug() << list;                            // 结果12,14,99,231,7

    QRegExp rxlen("(\\d+)(?:\\s*)(cm|inch)");
    int pos3 = rxlen.indexIn("Length: 189cm");
    if (pos3 > -1) {
        QString value = rxlen.cap(1);            // 结果为189
        QString unit = rxlen.cap(2);             // 结果为cm
        QString string = rxlen.cap(0);           // 结果为189cm
        qDebug() << value << unit << string;
    }

    QRegExp rx5("\\b(\\w+)\\W+\\1\\b");
    rx5.setCaseSensitivity(Qt::CaseInsensitive); // 设置不区分大小写
    qDebug() << rx5.indexIn("Hello--hello");     // 结果为0
    qDebug() << rx5.cap(1);                      // 结果为Hello

    QRegExp rx6("\\b你好\\b");                  // 匹配中文
    qDebug() << rx6.indexIn("你好");            // 结果为0
    qDebug() << rx6.cap(0); // 整个字符串完全匹配,使用cap(0)捕获,结果为“你好”

5 QRegularExpression

Qt5中新类,实现了于Perl兼容的正则表达式,这里的正则表达式由模式字符串和一组模式选项。

5.1 模式字符串

QRegularExpression re("a pattern");//构造函数设置模式串
    QRegularExpression re2;
    re2.setPattern("a pattern");

5.2 设置模式

设置模式

re.setPatternOptions(QRegularExpression::MultilineOption);
    QRegularExpression::PatternOptions option = re.patternOptions();

模式选项
在这里插入图片描述
在这里插入图片描述
示例:

  QRegularExpression re("^(\\d\\d)/(\\d\\d)/(\\d\\d\\d\\d)$");
    QRegularExpressionMatch match = re.match("08/12/1985");
    if (match.hasMatch()) {
        QString matched = match.captured(0);
        QString day = match.captured(1);
        QString month = match.captured(2);
        QString year = match.captured(3);
        qDebug() << "matched: " << matched << endl
                 << "day: " << day << endl
                 << "month: " << month << endl
                 << "year: " << year;
    }

    QString pattern("^(Jan|Feb|Mar|Apr|May) \\d\\d?, \\d\\d\\d\\d$");
    QRegularExpression re1(pattern);

    QString input("Jan 21,");
    QRegularExpressionMatch match1 = re1.match(input, 0,
                                               QRegularExpression::PartialPreferCompleteMatch);
    bool hasMatch = match1.hasMatch();
    bool hasPartialMatch = match1.hasPartialMatch();

    qDebug() << "hasMatch: " << hasMatch << "hasParticalMatch: " << hasPartialMatch;
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁星蓝雨

如果觉得文章不错可以请喝咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值