如何实现FSM以完成命令行工具输出的解析任务?
基于FSM解析命令行工具输出的最简实现方案
针对这个场景,最容易落地的是逐行驱动的单层有限状态机,无需引入第三方FSM框架,纯原生代码就能实现,核心只有三个组成部分:
- 状态枚举:只定义实际需要用到的状态即可,不要做冗余设计。比如解析
git status输出的场景,只需要定义INIT、IN_STAGED_SECTION、IN_UNSTAGED_SECTION、IN_UNTRACKED_SECTION几个必要状态,用普通常量或者枚举类实现都可以。 - 单全局状态变量:全程只维护一个当前状态变量,初始值设为初始状态,不需要多状态嵌套或者状态栈,绝大多数平面结构的命令行输出完全不需要复杂的状态管理。
- 逐行匹配的迁移逻辑:每读取一行命令行输出,就基于当前状态匹配该行的特征(前缀、关键字、正则规则都可以),执行两个操作:要么提取当前行的有效数据,要么切换当前状态,没有匹配项就保持原状态跳过当前行即可。
以下是Python的极简实现示例,不需要任何额外依赖:
# 定义状态常量 STATE_INIT = 0 STATE_IN_STAGED = 1 STATE_IN_UNSTAGED = 2 current_state = STATE_INIT parse_result = {"staged_files": [], "unstaged_files": []} # 这里的cmd_output是你从subprocess等渠道拿到的命令行输出内容 for line in cmd_output.splitlines(): line = line.strip() if current_state == STATE_INIT: if line.startswith("Changes to be committed:"): current_state = STATE_IN_STAGED elif line.startswith("Changes not staged for commit:"): current_state = STATE_IN_UNSTAGED elif current_state == STATE_IN_STAGED: if line.startswith("Changes not staged for commit:"): current_state = STATE_IN_UNSTAGED elif line.startswith("\t"): # 匹配文件行的缩进前缀 parse_result["staged_files"].append(line.strip()) elif current_state == STATE_IN_UNSTAGED: if line.startswith("Untracked files:"): # 不需要解析的段落直接切回初始状态跳过 current_state = STATE_INIT elif line.startswith("\t"): parse_result["unstaged_files"].append(line.strip())
这个方案逻辑直观,调试成本极低,出问题只要打印当前状态和当前行就能快速定位故障,覆盖90%以上的命令行输出解析场景,性能也完全够用,每秒可以处理上万行输出。
内容的提问来源于stack exchange,提问作者ADBeveridge
相关产品推荐
相关产品推荐

