Python解析自定义布尔表达式 为未知作业名添加前缀的实现方案咨询
实现方案
你可以直接用Python的lark库实现自定义语法解析,全程不需要手写复杂的状态机或递归下降逻辑,100行以内就能完成需求。
步骤1:安装依赖
pip install lark
步骤2:定义语法规则
针对你的布尔表达式场景,语法规则定义如下:
from lark import Lark, Transformer, v_args grammar = """ ?expr: expr "&" term -> and_op | expr "|" term -> or_op | term ?term: "(" expr ")" | state_call state_call: STATE "(" job_name ("," arg)* ")" STATE: "s" | "f" | "d" | "n" | "t" job_name: /[a-zA-Z0-9_]{6,}/ arg: ESCAPED_STRING | NUMBER %import common.ESCAPED_STRING %import common.NUMBER %import common.WS %ignore WS """
步骤3:编写替换逻辑
用lark的Transformer节点处理逻辑,直接替换作业名节点的内容,再生成新的表达式即可:
@v_args(inline=True) class JobPrefixTransformer(Transformer): def __init__(self, prefix): self.prefix = prefix def job_name(self, name): return f"{self.prefix}_{name}" def state_call(self, state, job_name, *args): args_str = ", ".join(args) if args else "" if args_str: return f"{state}({job_name}, {args_str})" return f"{state}({job_name})" def and_op(self, left, right): return f"{left} & {right}" def or_op(self, left, right): return f"{left} | {right}" def term(self, content): if isinstance(content, list): return f"({content[0]})" return content # 测试代码 if __name__ == "__main__": parser = Lark(grammar, start="expr") input_expr = '( s(job_A_123, "11:00") & f(job_B_456) ) | ( s(job_C_789) & t(job_D_012) )' tree = parser.parse(input_expr) transformer = JobPrefixTransformer(prefix="prefix") output_expr = transformer.transform(tree) print(output_expr)
运行上面的代码就能得到你要的输出结果:
( s(prefix_job_A_123, "11:00") & f(prefix_job_B_456) ) | ( s(prefix_job_C_789) & t(prefix_job_D_012) )
扩展说明
- 如果需要完全保留原表达式的空格、换行等格式,可以开启lark的
propagate_positions参数,解析时记录每个节点的原始位置,替换后按位置拼接字符串即可,不会改动原有格式。 - 语法支持任意层级的括号嵌套,完全覆盖你提到的非正则场景的布尔表达式结构。
- 如果后续新增状态码、参数类型,只需要修改grammar里的对应规则即可,不需要改动替换逻辑。
内容的提问来源于stack exchange,提问作者devprog
相关产品推荐
相关产品推荐

