位置:首页 > C++ > c++ 正则表达 regex匹配提取替换示例

c++ 正则表达 regex匹配提取替换示例

时间:2026-08-10  |  作者:夜鞌不睡  |  阅读:0

在C++中,正则表达式常用于文本查找、格式校验、内容提取和批量替换。本文围绕标准库regex组件,补充字符类、锚点、量词、分组与转义等常用语法,结合可直接编译运行的完整示例说明匹配、提取、遍历、替换和异常处理的实际用法。

正则表达式的基本用法

C++标准库在regex头文件中提供正则表达式支持。使用时先创建std::regex对象,再根据任务选择完整匹配、局部搜索或内容替换。默认语法接近ECMAScript,普通字符表示自身,点号匹配除换行符外的单个字符,星号表示前一项出现零次或多次,加号表示出现一次或多次,问号表示出现零次或一次。除了这些基础量词,实际开发中还常用字符类如[abc]、范围如[A-Z]、数字类d、空白类s、锚点^和$、数量词{m,n}、圆括号捕获组、竖线选择符a|b等语法。若需要跨行匹配任意字符,不能只依赖点号,通常应明确写成[sS]这类模式。书写规则时还要区分普通字符串和原始字符串:普通字符串中的d要写成"d",原始字符串R"(d)"则更直观。

  • std::regex_match用于判断整个字符串是否符合规则。
  • std::regex_search用于查找字符串中是否存在符合规则的片段。
  • std::regex_replace用于将所有符合规则的内容替换为指定文本。

匹配与格式校验

格式校验通常要求输入内容从头到尾都符合规则,因此适合使用std::regex_match。编写模式时应明确字符范围和长度,避免使用过于宽泛的通配规则。例如校验由字母开头、后接字母或数字的标识符,可以使用原始字符串保存模式,减少反斜杠转义带来的阅读负担。规则[A-Za-z][A-Za-z0-9]{2,15}表示首字符必须是字母,后面再跟2到15个字母或数字,因此总长度实际是3到16个字符。若目标长度不是3到16位,就要同步调整{2,15}这一段。下面是一个可直接编译运行的最小完整示例。

  • std::regex rule(R"([A-Za-z][A-Za-z0-9]{2,15})");
  • bool valid = std::regex_match(input, rule);
  • 原始字符串R"()"可以让反斜杠等正则字符保持直观。
  • 示例程序:

    #include 
    #include 
    #include 
    
    int main() {
        std::regex rule(R"([A-Za-z][A-Za-z0-9]{2,15})");
        std::string ok = "Code88";
        std::string shortName = "A1";
        std::string badStart = "9Code";
    
        std::cout << ok << " -> " << std::regex_match(ok, rule) << 'n';
        std::cout << shortName << " -> " << std::regex_match(shortName, rule) << 'n';
        std::cout << badStart << " -> " << std::regex_match(badStart, rule) << 'n';
    }

    输出结果:Code88 -> 1;A1 -> 0;9Code -> 0。

搜索与分组提取

需要从一段文本中提取部分内容时,可配合std::smatch和std::regex_search使用。匹配成功后,下标零保存完整结果,后续下标依次对应圆括号定义的捕获组。访问分组前应先确认匹配成功,并检查分组数量,避免读取不存在的结果。下面的日期提取程序包含头文件、输入文本、调用方式和输出结果,便于直接验证。

  • std::regex rule(R"((d{4})-(d{2})-(d{2}))");
  • std::smatch result;
  • 匹配成功后,result[1]、result[2]和result[3]分别保存年、月、日。
  • 示例程序:

    #include 
    #include 
    #include 
    
    int main() {
        std::string text = "today is 2026-08-05.";
        std::regex rule(R"((d{4})-(d{2})-(d{2}))");
        std::smatch result;
    
        if (std::regex_search(text, result, rule) && result.size() >= 4) {
            std::cout << "full: " << result[0].str() << 'n';
            std::cout << "year: " << result[1].str() << 'n';
            std::cout << "month: " << result[2].str() << 'n';
            std::cout << "day: " << result[3].str() << 'n';
        }
    }

    输出结果:full: 2026-08-05;year: 2026;month: 08;day: 05。

遍历全部匹配结果

std::regex_search通常只返回当前搜索范围内的第一个结果。若要提取文本中的全部匹配项,可以使用std::sregex_iterator遍历,也可以在每次匹配后从剩余文本继续搜索。迭代器方式结构更清晰,适合日志分析、编号提取和批量数据清洗。下面用完整程序演示如何遍历文本中的全部数字编号。

  • std::sregex_iterator begin(text.begin(), text.end(), rule);
  • std::sregex_iterator end;
  • 从begin遍历到end即可依次读取每个匹配结果。
  • 示例程序:

    #include 
    #include 
    #include 
    
    int main() {
        std::string text = "item12 item34 item567";
        std::regex rule(R"(d+)");
        std::sregex_iterator begin(text.begin(), text.end(), rule);
        std::sregex_iterator end;
    
        for (std::sregex_iterator it = begin; it != end; ++it) {
            std::cout << it->str() << 'n';
        }
    }

    输出结果依次为:12、34、567。

替换文本内容

std::regex_replace可以完成批量替换,并允许在替换模板中引用捕获组。例如调整日期字段顺序时,可以先捕获年、月、日,再在替换文本中重新排列。处理用户输入的替换内容时,需要留意其中是否包含具有特殊含义的引用符号。若只是做固定格式转换,先写出最小完整示例再扩展更稳妥。

  • 日期替换可以复用前文定义的年、月、日捕获规则。
  • std::string output = std::regex_replace(text, rule, "$3/$2/$1");
  • 替换模板中的$1、$2和$3对应前三个捕获组。
  • 示例程序:

    #include 
    #include 
    #include 
    
    int main() {
        std::string text = "截止日期: 2026-08-05";
        std::regex rule(R"((d{4})-(d{2})-(d{2}))");
        std::string output = std::regex_replace(text, rule, "$3/$2/$1");
    
        std::cout << output << 'n';
    }

    输出结果:截止日期: 05/08/2026。

性能与异常处理

正则模式构造可能消耗一定资源,重复使用同一规则时,应尽量复用已经创建的std::regex对象。复杂模式还可能导致匹配效率下降,因此应限制不必要的通配和回溯。模式语法错误会抛出std::regex_error,规则来自配置或外部输入时,不能只停留在原则说明,还应明确展示try/catch、错误记录和降级策略。常见做法是捕获const std::regex_error&,同时输出what()和code(),再返回失败状态或改用更保守的默认规则。

  • 将固定规则定义为可复用对象,避免在循环中反复构造。
  • 优先使用明确的字符范围和长度,减少模糊匹配。
  • 捕获std::regex_error后,可通过code方法判断错误类型。
  • 示例程序:

    #include 
    #include 
    #include 
    
    bool build_rule(const std::string& pattern, std::regex& outRule) {
        try {
            outRule = std::regex(pattern);
            return true;
        } catch (const std::regex_error& e) {
            std::cerr << "regex error: " << e.what() << 'n';
            std::cerr << "error code: " << static_cast(e.code()) << 'n';
            return false;
        }
    }
    
    int main() {
        std::regex rule;
        std::string badPattern = "([A-Z]+";
    
        if (!build_rule(badPattern, rule)) {
            std::cout << "fallback: skip current rule or switch to a safe default pattern." << 'n';
        }
    }

    该示例用于说明:当规则来自配置文件、数据库或用户输入时,构造失败后应返回false、中止当前匹配,或切换到预置的安全规则,而不是继续使用无效模式。

掌握匹配、搜索、提取和替换这四类操作后,便能处理多数C++文本任务。实际使用时应优先保证规则清晰可读,先用最小完整程序验证输入、输出和边界,再通过空字符串、超长文本、非法规则等异常数据检查结果是否符合预期。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多