17.3 Regular Expressions(正则表达式)

一个正则表达式是描述字符串序列的方法。

 

式子 说明
regex 表示有一个正则表达式的类
regex_match 将一个字符序列与一个正则表达式匹配
regex_search 寻找第一个去正则表达式匹配的子序列
regex_replace 使用给定格式替换一个正则表达式
sregex_iterator 迭代器适配器,调用regex_search来遍历一个string中所有匹配子串
smatch 容器类,保存在string中搜索结果
ssub_match string中匹配的子表达式的结果
#include <iostream>
#include <string>
#include <regex>
#include <vector>

using namespace std;

int main()
{
    string pattern = "[^c]ie";
    pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
    regex r(pattern, regex::icase);
    smatch results;
    string str;
    while (cin >> str) {
        if (str == "q")
            break;
        if (regex_search(str, results, r))
            cout << results.str() << endl;
    }

    system("PAUSE");
    return 0;
}

 

[^c]ei表示不是cei前面的字符串。默认情况下,regex使用的正则表达式语言是ECMAScript.在ECMAScript中,模式[[:alpha:]]匹配任意字母,符号+*分别表示我们希望“一个或多个”或“零个或多个”匹配。因此[[:alpha:]]将匹配零个或多个字母。

正则表达式网站

 

式子 说明
regex r(re) re表示一个正则表达式
regex r(re, f)

f是指出对象如何处理的标志,f通过下面的列出的值来设置,

如果未指定f,默认为ECMAScript

r1 = re r1中的正则表达式替换为re
r1.assign(re,f) 与使用=效果相同,f与上面f意义相同
r.mark_count() r中表达式的数目
r.flags() 返回r的标志集

定义在regexregex_constants::syntax_option_type

f为下面这些值

式子 说明
icase 在匹配过程中忽略大小写
nosubs 不保存匹配的子表达式
optimize 执行速度优先于构造速度
ECMAScript 使用ECMA-262指定语法
basic 使用POSIX基本的正则表达式语法
extended 使用POSIX扩展的正则表达式语法
awk 使用POSIX版本的awk语言的语法
grep 使用POSIX版本的grep的语法
egrep 使用POSIX版本的egrep的语法

 

#include <iostream>
#include <regex>
#include <string>

using namespace std;

int main()
{
    regex r("[[:alnum:]]+\\.(cpp|cxx|cc)$", regex::icase);
    smatch results;
    string filename;
    while(cin >> filename){
        if(regex_search(filename, results, r))
        cout << results.str() << endl;
    }
    
    system("PAUSE");
    return 0;
}

 

在正则表达式中, 小数点(.)表示匹配任意字符串,在字符串中要表示一个普通的反斜线需要写成\\

在字符串前置一个反斜线去掉其特殊含义

 

获取正则表达式错误的方法:

#include <iostream>
#include <regex>
#include <string>

using namespace std;

int main()
{
    try{
        regex r("[[:alnum:]+\\.(cpp|cxx|cc)$", regex::icase);
    }catch(regex_error e){
        cout << e.what() <<"\ncode:" << e.code() << endl;
    }
    smatch results;
    /*string filename;
    while(cin >> filename){
        if(regex_search(filename, results, r))
        cout << results.str() << endl;
    }*/
    
    system("PAUSE");
    return 0;
}

 

code()返回某个错误类型对应的数值编码

当我们将filename直接写成"hello.cc"时,这时变量类型为char*,应该使用cmatch储存结果。

 

 

 如果你在一个循环中使用正则表达式,应该在循环外创建它,而不是在每步迭代时都编译它。

 

使用regex迭代器类型搜寻

#include <iostream>
#include <regex>
#include <string>
#include <vector>

using namespace std;

int main()
{
    string pattern = "[^c]ei";
    pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
    regex r(pattern,regex::icase);
    string file;
    while (getline(cin, file)) {
        if (file == "q")
            break;
        for (sregex_iterator it(file.begin(), file.end(), r), end_it; it != end_it; ++it) {
            cout << it->str() << endl;
        }
    }

    system("PAUSE");
    return 0;
}

 

定大小输出匹配结果上下文

#include <iostream>
#include <string>
#include <regex>

using namespace std;

int main()
{
    string pattern("[^c]ei");
    pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
    regex r(pattern, regex::icase);
    string str;
    while (getline(cin, str)) {
        if (str == "q")
            break;
        for (sregex_iterator it(str.begin(), str.end(), r), it_end; it != it_end; ++it) {
            auto pos = it->prefix().length();
            pos = pos > 40 ? pos - 40 : 0;
            cout << it->prefix().str().substr(pos) << "\n\t<<<" <<
                it->str() << "<<<\n" << it->suffix().str().substr(1, 40) << endl;
        }
    }
    system("PAUSE");
    return 0;
}

 

 

#include <iostream>
#include <regex>
#include <string>
#include <fstream>

using namespace std;

bool checknum(const smatch& s) {
    if (s[1].matched) {
        return s[3].matched&& s[4].str() != "-" && s[4].str() != ".";
    }
    else
        return !s[3].matched && (s[4].str() == s[7].str());
}

int main()
{
    string pattern = "(\\()?(\\d{3})(\\))?([-.]|(\\s)*)?(\\d{3})([-.]|(\\s)*)?(\\d{4})";
    //string fmt = "$2.$6.$9";
    regex r(pattern);
    ifstream ss("D:\\test.txt", ios::in|ios::out);
    if (!ss) {
        cerr << "open failed!" << endl;
        system("PAUSE");
        return 1;
    }
    string line;
    while (getline(ss, line)) {
        if (line == "q")
            break;
        for (sregex_iterator it(line.begin(), line.end(), r), it_end; it != it_end; ++it) {
            if (checknum(*it)) {
                //cout << "号码匹配正确:" << it->format(fmt) << endl;
                cout << it->str() << endl;
            }
            else {
                cout << "号码匹配错误。" << endl;
            }
        }
    }

    system("PAUSE");
    return 0;
}

 

注释部分为替换操作,可以使用format,也可以使用regex_replace

 

要使用匹配标志,需要明确声明using namespace std::regex_constants;

 

#include <iostream>
#include <regex>
#include <string>
#include <fstream>

using namespace std;
using namespace std::regex_constants;

bool checknum(const smatch& s) {
    if (s[1].matched) {
        return s[3].matched&& s[4].str() != "-" && s[4].str() != ".";
    }
    else
        return !s[3].matched && (s[4].str() == s[7].str());
}

int main()
{
    string pattern = "(\\()?(\\d{3})(\\))?([-.]|(\\s)*)?(\\d{3})([-.]|(\\s)*)?(\\d{4})";
    string fmt = "$2.$6.$9";
    regex r(pattern);
    ifstream ss("D:\\test.txt", ios::in|ios::out);
    if (!ss) {
        cerr << "open failed!" << endl;
        system("PAUSE");
        return 1;
    }
    string line;
    while (getline(ss, line)) {
        if (line == "q")
            break;
        for (sregex_iterator it(line.begin(), line.end(), r), it_end; it != it_end; ++it) {
            if (checknum(*it)) {
                cout << "号码匹配正确:" << regex_replace(line, r, fmt, format_no_copy) << endl;
                //cout << it->str() << endl;
            }
            else {
                cout << "号码匹配错误。" << endl;
            }
        }
    }

    system("PAUSE");
    return 0;
}
posted @ 2019-02-27 17:46  Hk_Mayfly  阅读(184)  评论(0)    收藏  举报