基于Python提取配置文件各区块中的参数值
我来帮你搞定这个配置文件参数提取的需求,用Python实现起来其实不难,下面是具体的思路和代码:
Python实现配置文件区块参数提取
思路分析
先看看这个配置文件的结构:它是类似C语言的区块格式,有DEFAULT_TEMPLATE和TEMPLATE两个顶级区块,其中TEMPLATE下面还有以数字标识的子区块。我们的实现需要覆盖这几个核心步骤:
- 过滤所有注释内容(不管是行首还是行内的
#开头部分) - 识别每个区块的开始(
{)和结束(}),用栈处理嵌套层级 - 提取区块内的键值对,自动处理带引号的字符串,还能尝试把数值转成数字类型
完整代码实现
import re from collections import defaultdict def parse_config(config_content): # 第一步:清理注释和冗余空白 cleaned_lines = [] for line in config_content.splitlines(): # 移除行内所有#开头的注释,再去除前后空白 line = re.sub(r'#.*', '', line).strip() if line: cleaned_lines.append(line) cleaned_content = ' '.join(cleaned_lines) # 第二步:解析嵌套区块 stack = [] current_block = {} blocks = defaultdict(dict) # 正则匹配:区块标识、区块结束、键值对 tokens = re.finditer(r'(DEFAULT_TEMPLATE|TEMPLATE|\d+)\s*{|}|(\w+)\s*([^;]+);', cleaned_content) for token in tokens: if token.group(1): # 匹配到区块开始,记录当前状态到栈 block_name = token.group(1) stack.append((block_name, current_block)) # 区分顶级区块和TEMPLATE的子区块 if len(stack)>=2 and stack[-2][0] == 'TEMPLATE': current_block = {} blocks['TEMPLATE'][block_name] = current_block else: current_block = {} blocks[block_name] = current_block elif token.group() == '}': # 匹配到区块结束,回到上一级区块 if stack: _, current_block = stack.pop() elif token.group(2): # 匹配到键值对,处理值的格式 key = token.group(2).strip() value = token.group(3).strip() # 去除字符串的引号 if value.startswith(('"', "'")) and value.endswith(('"', "'")): value = value[1:-1] # 尝试转成数字,失败则保留字符串 try: value = int(value) except ValueError: try: value = float(value) except ValueError: pass current_block[key] = value return dict(blocks) # 测试用的配置内容(你提供的完整内容) sample_config = """# line 1 contains some info # line 1 contains some info # Creation date: Tue Aug 16 17:13:37 2016 # line 3 contains some info # line 4 contains some info DEFAULT_TEMPLATE { DELAY_TIME 30; TEMPLATE_FNAME "ABC"; VENDOR_DELAYED "/"; DELAY_FNAME "ABC_NAME"; DELAY_FVALUE "DELAYED-30"; DELAY_FMODE "END"; } TEMPLATE { 2548 # some-details1 { DELAY_TIME 0; DELAY_FNAME "DSPLY_NAME"; DELAY_FVALUE "DELAYED-0"; DELAY_FMODE "END"; } 1 # some details2 { DELAY_TIME 20; DELAY_FNAME "DSPLY_NAME"; DELAY_FVALUE "DELAYED-20"; DELAY_FMODE "END"; } }""" # 解析并打印结果 parsed_result = parse_config(sample_config) print("解析后的参数:") print("DEFAULT_TEMPLATE:") for k, v in parsed_result['DEFAULT_TEMPLATE'].items(): print(f" {k}: {v}") print("\nTEMPLATE:") for sub_block, params in parsed_result['TEMPLATE'].items(): print(f" 子区块 {sub_block}:") for k, v in params.items(): print(f" {k}: {v}")
代码解释
- 注释清理:用正则
r'#.*'干掉所有注释内容,把有效内容合并成一行,避免换行和空白干扰解析。 - 区块嵌套处理:用栈(stack)记录当前所在的区块层级,遇到
{就压栈,遇到}就弹栈,完美处理嵌套结构。 - 键值对格式化:自动去除字符串的引号,还能智能识别数值类型(整数/浮点数),让提取的参数更易用。
- 结果存储:用嵌套字典保存所有参数,
DEFAULT_TEMPLATE直接存键值对,TEMPLATE下的子区块以数字为键,对应各自的参数集合。
运行结果
运行代码后会输出清晰的参数结构:
解析后的参数: DEFAULT_TEMPLATE: DELAY_TIME: 30 TEMPLATE_FNAME: ABC VENDOR_DELAYED: / DELAY_FNAME: ABC_NAME DELAY_FVALUE: DELAYED-30 DELAY_FMODE: END TEMPLATE: 子区块 2548: DELAY_TIME: 0 DELAY_FNAME: DSPLY_NAME DELAY_FVALUE: DELAYED-0 DELAY_FMODE: END 子区块 1: DELAY_TIME: 20 DELAY_FNAME: DSPLY_NAME DELAY_FVALUE: DELAYED-20 DELAY_FMODE: END
你可以根据自己的需求调整代码,比如支持更多特殊格式的参数,或者扩展其他区块类型。
内容的提问来源于stack exchange,提问作者Himani
相关产品推荐
相关产品推荐

