C++中std::smatch和std::regex 的使用详解和代码示例

C++中std::smatch和std::regex使用详解

在 C++ 中,std::regexstd::smatch 是标准库 <regex> 中用于正则表达式处理的核心工具。下面是它们的详细使用说明和丰富的示例代码,适合日常开发中的字符串匹配、查找、替换等需求。


基本概念

  • std::regex:表示一个正则表达式对象
  • std::smatch:表示匹配结果,用于字符串(std::string)的匹配结果存储。
  • std::regex_match:整体匹配整个字符串。
  • std::regex_search:部分匹配,查找字符串中任意位置是否匹配。
  • std::regex_replace:替换匹配的子串。

常用头文件

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

1️、std::regex_match:整体匹配

#include <iostream>
#include <regex>

int main() {
    std::string str = "hello123";
    std::regex pattern("hello\\d+");  // 匹配 hello 后跟数字

    std::smatch result;  // 用于保存匹配结果
    if (std::regex_match(str, result, pattern)) {
        std::cout << "Full match: " << result[0] << std::endl;
    } else {
        std::cout << "No match." << std::endl;
    }

    return 0;
}

说明:

  • result[0] 是完整匹配内容
  • \\d+ 表示一个或多个数字(std::regex 中转义要写两个反斜杠)

2️、std::regex_search:部分匹配(子串匹配)

#include <iostream>
#include <regex>

int main() {
    std::string text = "My number is 2025-07-07.";
    std::regex date_regex(R"(\d{4}-\d{2}-\d{2})");  // 匹配日期格式
    std::smatch match;

    if (std::regex_search(text, match, date_regex)) {
        std::cout << "Found date: " << match[0] << std::endl;
    }

    return 0;
}

说明:

  • regex_search 适合用来“查找”是否包含某些子串。
  • R"()" 是原始字符串,不需要转义。

3️、使用分组提取(捕获组)

#include <iostream>
#include <regex>

int main() {
    std::string email = "contact: john.doe@example.com";
    std::regex email_regex(R"((\w+)\.(\w+)@(\w+\.\w+))");
    std::smatch result;

    if (std::regex_search(email, result, email_regex)) {
        std::cout << "Full: " << result[0] << std::endl;
        std::cout << "First Name: " << result[1] << std::endl;
        std::cout << "Last Name: " << result[2] << std::endl;
        std::cout << "Domain: " << result[3] << std::endl;
    }

    return 0;
}

说明:

  • result[n] 对应第 n 个括号里的捕获组(从 1 开始)
  • result[0] 总是表示整个匹配内容

4️、std::regex_replace:正则替换

#include <iostream>
#include <regex>

int main() {
    std::string text = "ID: abc123, ID: def456";
    std::regex pattern(R"(ID:\s\w+)");
    std::string replaced = std::regex_replace(text, pattern, "ID: [HIDDEN]");

    std::cout << "After replace: " << replaced << std::endl;
    return 0;
}

输出:

After replace: ID: [HIDDEN], ID: [HIDDEN]

5️、遍历所有匹配项(std::sregex_iterator

#include <iostream>
#include <regex>

int main() {
    std::string text = "Emails: one@test.com two@example.com";
    std::regex pattern(R"(\w+@\w+\.\w+)");
    std::sregex_iterator it(text.begin(), text.end(), pattern);
    std::sregex_iterator end;

    for (; it != end; ++it) {
        std::cout << "Found: " << it->str() << std::endl;
    }

    return 0;
}

6️、regex 选项(flags)

  • std::regex_constants::icase:忽略大小写
  • std::regex_constants::ECMAScript(默认)
  • std::regex_constants::extendedawkgrep

示例:

std::regex r("abc", std::regex_constants::icase);

常见问题注意

问题原因
匹配不成功正则表达式转义错误,例如忘记 \\d 写成 \d
std::regex_error 异常正则语法错误或表达式不合法
regex_match 匹配失败用于整体匹配,需与字符串完全一致
regex_search 更常用用于子串查找,灵活

总结

需求推荐方法
整体匹配std::regex_match
查找子串std::regex_search
提取子串分组std::smatch[i]
替换匹配内容std::regex_replace
多个匹配遍历std::sregex_iterator

正则匹配工具类封装示例

下面是一个通用的 C++ 正则匹配工具类封装,支持以下功能:

功能特性:

  1. 整体匹配fullMatch()
  2. 子串匹配search()
  3. 分组提取getMatchGroups()
  4. 批量匹配迭代器findAll()
  5. 替换匹配内容replace()
  6. 支持设置忽略大小写、自定义正则模式

RegexUtils.h 完整代码

#pragma once

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

class RegexUtils {
public:
    explicit RegexUtils(const std::string& pattern, bool ignoreCase = false)
    {
        if (ignoreCase) {
            regex_ = std::regex(pattern, std::regex::ECMAScript | std::regex::icase);
        } else {
            regex_ = std::regex(pattern, std::regex::ECMAScript);
        }
    }

    // 整体匹配
    bool fullMatch(const std::string& text) const {
        return std::regex_match(text, std::smatch{}, regex_);
    }

    // 子串搜索匹配
    std::optional<std::string> search(const std::string& text) const {
        std::smatch match;
        if (std::regex_search(text, match, regex_)) {
            return match.str(0);
        }
        return std::nullopt;
    }

    // 获取所有分组匹配
    std::vector<std::string> getMatchGroups(const std::string& text) const {
        std::smatch match;
        std::vector<std::string> results;
        if (std::regex_search(text, match, regex_)) {
            for (size_t i = 0; i < match.size(); ++i) {
                results.emplace_back(match[i].str());
            }
        }
        return results;
    }

    // 替换匹配内容
    std::string replace(const std::string& text, const std::string& replacement) const {
        return std::regex_replace(text, regex_, replacement);
    }

    // 查找所有匹配
    std::vector<std::string> findAll(const std::string& text) const {
        std::vector<std::string> results;
        auto begin = std::sregex_iterator(text.begin(), text.end(), regex_);
        auto end = std::sregex_iterator();
        for (auto it = begin; it != end; ++it) {
            results.push_back(it->str());
        }
        return results;
    }

private:
    std::regex regex_;
};

示例代码:main.cpp

#include "RegexUtils.h"

int main() {
    std::string text = "Emails: alice@test.com and bob@example.com";
    RegexUtils emailRegex(R"((\w+)@(\w+\.\w+))");

    // 搜索第一个匹配
    if (auto match = emailRegex.search(text)) {
        std::cout << "First match: " << *match << std::endl;
    }

    // 获取所有匹配
    auto allMatches = emailRegex.findAll(text);
    for (const auto& m : allMatches) {
        std::cout << "Found: " << m << std::endl;
    }

    // 分组提取
    auto groups = emailRegex.getMatchGroups("contact: john.doe@example.com");
    std::cout << "Captured groups:\n";
    for (const auto& g : groups) {
        std::cout << " - " << g << std::endl;
    }

    // 替换
    std::string replaced = emailRegex.replace(text, "[REDACTED]");
    std::cout << "After replacement: " << replaced << std::endl;

    return 0;
}

输出示例

First match: alice@test.com
Found: alice@test.com
Found: bob@example.com
Captured groups:
 - john
 - doe
 - example.com
After replacement: Emails: [REDACTED] and [REDACTED]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

点云SLAM

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值