C++第16课 正则表达式

1.C++正则

正则是一种规则,它用来匹配(进而捕获、替换)字符串。这种规则需要“模式”、“字符串”这两样东西,“模式”根据正则规则,来处理“字符串”。这种规则被许多语言支持,C++11以后才支持正则。

#### 具有特殊意义的元字符

\:\字符能够改变字符原本的含义

^:^字符指示字符串的头,且要求字符串以字符开头,不占位。\^表示一个真正的^符号。

$:$字符指示字符串的尾,且要求字符串以字符结尾,不占位。\$表示一个真正的$符号。

():分组,大正则中包含小正则。可以改变默认的优先级。在模式中可以使用\1来表示第一组已然捕获到的东西。

\b:指示字符串的边界(头/尾/空格左/空格右),字符\b要求边界的左边是字符,\b字符要求边界的右边是字符。

.:表示一个除了\n以外的任意一个字符。\\.表示一个真正的.符号。

|:字符串1|字符串2表示一个字符串,该字符串是字符串1、字符串2中的一个。|在正则中的优先级比较混乱,所以建议加上足够多的括号来分组。

[]:[字符1字符2字符3...]表示一个字符,该字符是字符1、字符2、字符3……中的某一个。中括号中出现的所有字符都是代表本身意思的字符(没有特殊含义),如[.]只能匹配.符号,而不能匹配任意符号。

[^字符1字符2字符3...]表示一个字符,该字符不是字符1、字符2、字符3……中的任何一个

[a-z]表示一个字符,该字符是a、b、c……z中的某一个

[^a-z]表示一个字符,该字符不是a、b、c……z中的任何一个

\w:表示一个字符,该字符是数字、字母、下划线中的某一个。等价于[(0-9)(a-z)(A-Z)(_)]

\W:表示一个字符,该字符不是数字、字母、下划线中的任何一个。等价于[]

\d表示一个字符,该字符是0、1、2……9中的某一个

\D表示一个字符,该字符不是0、1、2……9中的任何一个

\s表示一个字符,该字符是空白符(空格、制表符、换页符)2、代表出现次数的

## 量词元字符

*:字符*要求字符出现0到多次

+:字符+要求字符出现1到多次

?:字符?要求字符出现0次或1次

{n}:字符{n}要求字符出现n次

{n,}:字符{n,}要求字符出现n到多次

{n,m}:字符{n,m}要求字符出现n到m次、

所以含有`\`的元字符,在C++定义时,都要写成`\\`

## C++使用正则

## 匹配

`regex_match`和`regex_search`均可以进行匹配,返回一个布尔类型,匹配成功为true,匹配失败为false。

前者要求完全匹配,后者要求子串匹配即可

### 捕获

捕获就是先匹配,然后将匹配结果存储下来。捕获同样是使用上面介绍的那两个函数,仍然区分为整串匹配和子串匹配。

模式中一般要有分组(因为捕捉的正是分组匹配的结果)
定义一个STL容器smatch,用来保存捕捉的结果
reg_search函数匹配,用smatch的实例存储匹配的结果
m.size(),查看捕捉到的个数;

m.str(i),查看捕捉到的字符串;

【注意:m.str(0)一定是整个正则匹配到的部分,

m.str(1)及以后才是分组捕获的结果】
m.prefix().str()获取整个匹配之前的字符串;

m.suffix().str()获取整个匹配之后的字符串

1. 获取第i个匹配`m.str(i)`,还有其他等价写法:`m[i].str()`、`*(m.begin() + i)`
2. 模式其实可以不分组…这样就只有`m.str(0)`捕捉到整个串,没有`m.str(1)`其他的了。

由于`regex_replace`方法**只能捕捉到第一个匹配**,想要捕捉到每一个匹配,以及匹配内的分组,需要使用另外一种方法:

**步骤:**

1. 正则内有分组
2. 定义迭代器的同时初始化迭代器,使其指向一个`smatch`实例的数组。
3. 定义`end`,标志`smatch`实例的数组的末尾
4. 使用迭代器遍历数组

### 捕捉的同时生成新串

```c++
#include <bits/stdc++.h>
using namespace std;
int main()
{
string str = "boo@gmail.com boqian@hotmail.com bo_qian@163.com";
regex e("([[:w:]]+)@([[:w:]]+)\.com");
cout << regex_replace(str, e, "$1 is on $2\n", regex_constants::format_no_copy); // 除了捕捉到的组以外,其他的东西均舍弃
return 0;
}

```

regex_replace除了regex_constants::format_no_copy以外,还有其他flag,如regex_constants::format_first_only表示只取“大匹配1”,而忽略其他。
flag和flag之间通过|相连接。
regex_match和regex_search也有自己的flag,如用于忽略英文字母大小写的regex_constants::icase

//No.1 字符串匹配: regex_match
void  testMatch() 
{
    //bool regex_match(const char* str,regex reg);
    //满足正则标准返回true ,不满足返回false
    //1.1 判断输入用户名是否是字符串
    char userName[20]="";
    while (1) 
    {
        cout << "输入用户名:";
        cin >> userName;
        // \变为 "\\" ,因为C语言转义符问题
        regex reg("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
        bool result = regex_match(userName, reg);
        if (result == true) 
        {
            cout << "输入的是邮箱!" << endl;
            break;
        }
        else 
        {
            cout << "输入的不是邮箱!重新输入" << endl;
        }
    }
    //1.2 完全匹配问题
    string str = { "ILoveyou1314" };
    regex reg("[a-z0-9]+");   //最少1次的 a-z或者0-9
    bool result = regex_match(str, reg);
    if (result) 
    {
        cout << "完全匹配" << endl;
    }
    str = "iloveyou1314";
    result=regex_match(str, reg);
    if (result) 
    {
        cout << "完全匹配" << endl;
    }
    //1.3 '\'改为"\\"
    //1.4 忽略大写做正则匹配
    str = "ILoveyou1314";
    regex regstr("[a-z0-9]+", regex_constants::icase);
    result = regex_match(str, regstr);
    if (result) 
    {
        cout << "忽略大小写" << endl;
    }
}
//No.2 字符串的捕获: regex_search
void  testSearch() 
{    
    //No.1 捕获第一次满足条件的
    //bool regex_search(const char* str,smatch result,regex reg);
    string str = "ILoveyou13you14";
    smatch result;
    bool flag = regex_search(str, result, regex("\\d+"));
    if (flag) 
    {
        cout << "size:" << result.size() << endl;
        //匹配到的字符串
        for (int i = 0; i < result.size(); i++) 
        {
            cout << result.str() << "\t";
        }
        cout << endl;
        //匹配到的字符串的前后缀
        cout << result.prefix() << endl;
        cout << result.suffix() << endl;

    }

    //No.2 捕获后续能够匹配的字符串
    //sregex_iterator 
    regex reg("\\d+");
    sregex_iterator pos(str.begin(), str.end(), reg);
    //str
    sregex_iterator end;
    while (pos != end) 
    {
        cout << pos->str() << "\t";
        pos++;
    }
    cout << endl;
    //No.3 把每一部分都得到
    //sregex_token_iterator(iterator begin,iterator end,regex regx,flag)
    //flag: 0 所有匹配到的
    //flag:-1 存储所有的不匹配的
    str = "I13Love14you520";
    regex test("\\d+");
    sregex_token_iterator pos1(str.begin(), str.end(), test, 0);
    sregex_token_iterator end1;
    while (pos1 != end1) 
    {
        cout << pos1->str() << "\t";
        pos1++;
    }
    cout << endl;

}
//No.3 字符串的替换 :regex_replace
void testReplace() 
{
    //1.基本用法
    // string regex_replace(string str,regex regx,string replacestr);
    string str = "ILoveyou13Love14me";
    regex reg("\\d+");
    cout << regex_replace(str, reg, "") << endl;
    //2.按照特定条件做替换
    str = "ILoveyou13Love14me";
    //string regex_replace(string str,regex regx,string replacestr,regex_constants );
    //regex_constants::format_first_only;
    cout << regex_replace(str, reg, "@", regex_constants::format_first_only) << endl;
    //不包含原来不满足条件的字符串
    cout << regex_replace(str, reg, "@", regex_constants::format_no_copy) << endl;
}

 

posted @ 2021-09-11 19:16  Creature_lurk  阅读(211)  评论(0编辑  收藏  举报