You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++ std::regex_match提取状态机语句中的多组有效内容?

改进C++ std::regex_match提取状态机元素的实现

我需要从状态机定义字符串中提取核心元素(源状态A、事件e、守卫guard、动作action、目标状态B),用于生成PlantUML状态图。之前用字符串分割/修剪的方式处理,现在尝试用C++的std::regex_match实现,但当前正则提取的结果会带入多余字符(如+、[]、/),请求改进。

示例状态机字符串

hsm::state<A>  = hsm::state<B>
hsm::state<A> + hsm::event<e> = hsm::state<B>
hsm::state<A> [guard] = hsm::state<B>
hsm::state<A> / action = hsm::state<B>
hsm::state<A> + hsm::event<e> [guard] = hsm::state<B>
hsm::state<A> [guard] / action = hsm::state<B>
hsm::state<A> + hsm::event<e> [guard] / action = hsm::state<B>

现有代码

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

using namespace std;

int main(int argc, char* argv[])
{
    std::regex re{"(.*hsm::state<.[^>]*>)(.*hsm::event<.[^>]*>)?(.*\\[.[^>]*\\])?(.*/.[^=]*)?.*(hsm::state<.[^>]*>).*"};

    ifstream file(argv[1]);

    for (std::string line; getline(file, line);) {
        cout << "[" << line << "]" << endl;
        std::smatch match;

        if (std::regex_match(line, match, re)) {
            const char* names[] = {"", "source", "event ", "guard ", "action", "target", "", "", ""};
            for (size_t i = 1; i < match.size(); ++i) {
                cout << "   m[" << i << "]: " << names[i] << ": [" << match[i] << "]" << endl;
            }
        }
    }
}

改进思路

核心是调整正则表达式,通过精准捕获组直接提取需要的核心内容,而非捕获包含多余符号的整段文本。具体调整点:

  • 对源状态、目标状态,直接捕获<>内部的状态名(如A、B)
  • 对事件,跳过 + hsm::event<前缀,直接捕获<>内部的事件名(如e)
  • 对守卫,跳过[前缀和]后缀,直接捕获括号内的守卫内容
  • 对动作,跳过/前缀,直接捕获动作内容

改进后的代码

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

using namespace std;

int main(int argc, char* argv[])
{
    // 正则说明:
    // 1. 源状态:捕获hsm::state<...>中的...部分
    // 2. 事件:可选,匹配+ hsm::event<...>并捕获...部分
    // 3. 守卫:可选,匹配[...]并捕获...部分
    // 4. 动作:可选,匹配/ ... 并捕获...部分(直到=前)
    // 5. 目标状态:捕获hsm::state<...>中的...部分
    std::regex re{R"(hsm::state<([^>]*)>\s*(?:\+\s*hsm::event<([^>]*)>)?\s*(?:\[([^\]]*)\])?\s*(?:/\s*([^=]*))?\s*=\s*hsm::state<([^>]*)>)"};

    ifstream file(argv[1]);

    for (std::string line; getline(file, line);) {
        cout << "[" << line << "]" << endl;
        std::smatch match;

        if (std::regex_match(line, match, re)) {
            const char* names[] = {"", "source", "event", "guard", "action", "target"};
            for (size_t i = 1; i < match.size(); ++i) {
                if (!match[i].str().empty()) {
                    cout << "   m[" << i << "]: " << names[i] << ": [" << match[i].str() << "]" << endl;
                }
            }
        }
    }
    return 0;
}

关键正则解释

  • hsm::state<([^>]*)>:匹配源状态定义,([^>]*)捕获<>内的状态名(非>的任意字符)
  • (?:\+\s*hsm::event<([^>]*)>)?:非捕获组包裹事件匹配,?:表示不捕获整个前缀,只捕获<>内的事件名,?表示该部分可选
  • (?:\[([^\]]*)\])?:非捕获组包裹守卫匹配,捕获[]内的内容,可选
  • (?:/\s*([^=]*))?:非捕获组包裹动作匹配,捕获/ 后到=前的内容,可选
  • \s*=\s*hsm::state<([^>]*)>:匹配等号和目标状态,捕获目标状态名

测试效果

对于所有示例字符串,提取的内容均为干净的核心值:

  • 源状态:A
  • 事件(存在时):e
  • 守卫(存在时):guard
  • 动作(存在时):action
  • 目标状态:B

内容的提问来源于stack exchange,提问作者David Fleury

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:00:28