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

PyParsing解析代码块时,如何仅提取模块名及.obs前缀的参数

解决PyParsing提取特定前缀参数的问题

看起来你已经走对了大半路,问题出在没有对参数做针对性过滤——你的当前parser会匹配所有参数,而不是只保留.obs开头的。下面给你两种可行的实现思路,都能精准得到你想要的结果:

方法一:解析时直接过滤并保留目标参数

这种方法在定义parser时就区分“需要保留的obs参数”和“需要跳过的其他参数”,解析后直接得到目标结果,不用二次处理:

from pyparsing import Word, alphanums, Suppress, ZeroOrMore, Optional, identifier

# 定义基础标识符(字母、数字、下划线)
basic_identifier = Word(alphanums + '_')

# 定义需要保留的obs参数名:必须以.obs开头
obs_param_name = ('.' + basic_identifier).addCondition(lambda s: s.startswith('.obs'))

# 定义非obs参数:匹配后直接跳过,不保留结果
non_obs_param = Suppress(
    ('.' + basic_identifier).addCondition(lambda s: not s.startswith('.obs'))
    + Suppress('(') + basic_identifier + Suppress(')')
    + Optional(Suppress(','))  # 处理参数后的逗号
)

# 定义obs参数:匹配后保留参数名,处理后续逗号
obs_param = (
    obs_param_name
    + Suppress('(') + basic_identifier + Suppress(')')
    + Optional(Suppress(','))
)

# 模块整体解析规则
module_parser = (
    basic_identifier.setResultsName("module_name")
    + Suppress('(')
    + ZeroOrMore(non_obs_param | obs_param).setResultsName("obs_params")
    + Suppress(')')
    + Suppress(';')
)

# 测试解析
test_text = """abc_module ( .test_test1 ( test_test_real1 ), .abc_test ( abc_test_real ), .obs_test_one ( obs_test_one_real ), .obs_test_two ( obs_test_two_real ) );
cfg_module ( .test_test2 ( test_test_real2 ), .xyz_test ( xyz_test_real ) );
xyz_module ( .test_test2 ( test_test_real2 ), .xyz_test ( xyz_test_real ), .obs_test_three ( obs_test_three_real ), .ahc_test ( ahc_test_real ), .obs_test_four ( obs_test_four_real ) );"""

# 提取所有模块的结果
results = module_parser.searchString(test_text)

# 整理成你需要的格式
parse_result = [[mod.module_name] + list(mod.obs_params) for mod in results]
print(parse_result)

运行这段代码会直接输出你期望的结果:

[['abc_module', '.obs_test_one', '.obs_test_two'], ['cfg_module'], ['xyz_module', '.obs_test_three', '.obs_test_four']]

方法二:先解析所有参数,再二次过滤

如果你想保留原有parser的大部分结构,也可以先解析出所有参数,再用Python列表推导式过滤出.obs开头的项:

from pyparsing import Word, alphanums, Suppress, OneOrMore, Optional, identifier

# 基础标识符定义
basic_identifier = Word(alphanums + '_')
keyword = Word(alphanums + '_' + '.')

# 调整原有parser,先捕获所有参数
sub_module_parser = (
    basic_identifier.setResultsName("module_name")
    + Suppress("(")
    + OneOrMore(
        keyword.setResultsName("param", listAllMatches=True)
        + Suppress("(" + keyword + ")")
        + Optional(Suppress(","))
    )
    + Suppress(")")
    + Suppress(";")
)

# 解析文本
test_text = """abc_module ( .test_test1 ( test_test_real1 ), .abc_test ( abc_test_real ), .obs_test_one ( obs_test_one_real ), .obs_test_two ( obs_test_two_real ) );
cfg_module ( .test_test2 ( test_test_real2 ), .xyz_test ( xyz_test_real ) );
xyz_module ( .test_test2 ( test_test_real2 ), .xyz_test ( xyz_test_real ), .obs_test_three ( obs_test_three_real ), .ahc_test ( ahc_test_real ), .obs_test_four ( obs_test_four_real ) );"""

results = sub_module_parser.searchString(test_text)

# 过滤出.obs开头的参数
parse_result = []
for mod in results:
    obs_params = [p for p in mod.param if p.startswith('.obs')]
    parse_result.append([mod.module_name] + obs_params)

print(parse_result)

这种方法更灵活,如果你之后需要处理其他类型的参数,只需要修改过滤条件即可。

关键说明

  • 避免用skipTo:skipTo是模糊匹配,容易跳过过多内容导致解析错误,针对这种有明确格式的文本,用addCondition做精准过滤更可靠。
  • setResultsName的listAllMatches=True:当同一个结果名会匹配多次时,需要加上这个参数才能收集到所有匹配项,否则只会保留最后一个。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 12:19:07