std::smatch 是 C++ 标准库中用于存储正则表达式匹配结果的容器类型。让我详细分析它的作用:
(1) smatch 是 std::match_results<std::string::const_iterator> 的类型别名
(2) 专门用于存储 std::string 的正则匹配结果

以下面这段代码为例:

std::string& filename; 

std::regex number_regex(R"((\d+))");

std::smatch match;
 
if (std::regex_search(filename, match, number_regex)) {
    try {
        return std::stoi(match[1].str());
    }
    catch (...) {
        return -1;
    }
}

这段代码的作用是从文件名中提取第一个数字并返回。让我逐句解析:

std::string& filename;  // 文件名的引用(作为参数传入)

std::regex number_regex(R"((\d+))");  
// 创建正则表达式对象:
// \d+ : 匹配一个或多个数字
// () : 捕获组,保存匹配的数字

std::smatch match;  
// 创建匹配结果容器(注意:你的代码中重复声明了两次)

if (std::regex_search(filename, match, number_regex)) {
    // 在 filename 中搜索匹配 number_regex 的内容
    // 如果找到,match 会保存匹配结果
    
    try {
        return std::stoi(match[1].str());
        // match[1]: 第一个捕获组(括号内的数字)
        // .str(): 转换为字符串
        // std::stoi(): 将字符串转换为整数并返回
    }
    catch (...) {
        return -1;  // 如果转换失败,返回 -1
    }
}

那么在这几句代码中,使用match[0]和match[1]有什么区别吗?
match[0]:存储完整匹配的内容(整个正则表达式匹配到的字符串)
match[1]:存储第一个捕获组的内容(第一对括号 () 内匹配的内容)

之前的代码中因为只设置了一个捕获组,所以match[0]和match[1]相同。

当正则表达式更复杂时
示例 1:带前缀的匹配

std::string filename = "file_123.txt";
std::regex pattern(R"(file_(\d+))");  // 注意:只有数字部分有括号
std::smatch match;

if (std::regex_search(filename, match, pattern)) {
    std::cout << "match[0]: " << match[0] << "\n";  // "file_123"
    std::cout << "match[1]: " << match[1] << "\n";  // "123"
}

示例 2:多个捕获组

std::string filename = "report_2024_10_21.pdf";
std::regex pattern(R"((\d{4})_(\d{2})_(\d{2}))");
std::smatch match;

if (std::regex_search(filename, match, pattern)) {
    std::cout << "match[0]: " << match[0] << "\n";  // "2024_10_21"
    std::cout << "match[1]: " << match[1] << "\n";  // "2024"
    std::cout << "match[2]: " << match[2] << "\n";  // "10"
    std::cout << "match[3]: " << match[3] << "\n";  // "21"
}

示例 3:非捕获组

std::string filename = "image_001.jpg";
std::regex pattern(R"((?:image_)(\d+))");  // (?:...) 是非捕获组
std::smatch match;

if (std::regex_search(filename, match, pattern)) {
    std::cout << "match[0]: " << match[0] << "\n";  // "image_001"
    std::cout << "match[1]: " << match[1] << "\n";  // "001"
    // 没有 match[2],因为 (?:...) 不算捕获组
}
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐