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

如何用Python正则表达式解析与分词钻孔机器人指令文件?

用Python正则处理带递归多行REPEAT指令的钻孔机器人指令解析方案

针对你需要解析带递归嵌套、跨多行REPEAT指令的钻孔机器人指令集问题,以下是基于Python正则的具体实现方案:

核心思路:递归正则匹配嵌套结构

Python的re模块支持递归正则表达式(通过命名组引用(?&group_name)实现),可以直接处理REPEAT指令的嵌套需求。我们先定义基础指令的匹配规则,再递归匹配REPEAT块内的任意指令(包括嵌套的REPEAT)。

1. 正则模式定义

import re

# 正则模式:匹配所有合法指令,支持递归嵌套REPEAT
# 使用re.VERBOSE提高可读性,re.MULTILINE适配多行内容
cmd_pattern = re.compile(r'''
    (?P<instruction>
        # 旋转指令
        (ROTATE (LEFT|RIGHT))
        # 移动指令:N为自然数(从1开始)
        | (GO ([1-9]\d*) UNITS)
        # 钻孔指令
        | DRILL
        # 递归REPEAT指令:匹配{...}内的所有指令(含嵌套REPEAT)
        | REPEAT ([1-9]\d*) TIMES \s* {
            \s* (?P<block>(?:(?&instruction)\s*)*) \s*
        }
    )
    # 匹配指令间的任意空白(空格、换行、制表符)
    \s*
''', re.VERBOSE | re.MULTILINE)

2. 行号追踪与指令解析

要准确定位语法错误的行号,需要先读取整个文件内容,通过匹配位置计算对应的行号。同时遍历所有匹配结果,检查未匹配的内容以识别语法错误:

def parse_commands(file_path):
    with open(file_path, 'r', encoding='utf-8') as f:
        content = f.read()

    last_match_end = 0
    # 遍历所有合法指令匹配
    for match in cmd_pattern.finditer(content):
        # 计算当前指令的行号
        current_line = content[:match.start()].count('\n') + 1

        # 检查匹配前的未解析内容(语法错误)
        if match.start() > last_match_end:
            invalid_content = content[last_match_end:match.start()].strip()
            if invalid_content:
                print(f"语法错误:第{current_line}行,无效指令片段 '{invalid_content}'")

        # 提取指令类型并执行对应逻辑
        full_cmd = match.group('instruction')
        if full_cmd.startswith('ROTATE'):
            direction = match.group(2)
            print(f"第{current_line}行:执行旋转{direction}")
            # 调用机器人旋转方法:robot.rotate(direction)
        elif full_cmd.startswith('GO'):
            units = int(match.group(5))
            print(f"第{current_line}行:移动{units}单位")
            # 调用机器人移动方法:robot.go(units)
        elif full_cmd == 'DRILL':
            print(f"第{current_line}行:执行钻孔")
            # 调用机器人钻孔方法:robot.drill()
        elif full_cmd.startswith('REPEAT'):
            repeat_times = int(match.group(6))
            block_content = match.group('block')
            print(f"第{current_line}行:重复{repeat_times}次执行块内容")
            # 递归处理REPEAT块内的指令
            process_repeat_block(block_content, current_line)

        last_match_end = match.end()

    # 检查文件末尾的未解析内容
    if last_match_end < len(content):
        error_line = content[:last_match_end].count('\n') + 1
        invalid_content = content[last_match_end:].strip()
        if invalid_content:
            print(f"语法错误:第{error_line}行,无效指令片段 '{invalid_content}'")

def process_repeat_block(block_content, start_line):
    """递归处理REPEAT块内的指令,计算块内指令的实际行号"""
    for match in cmd_pattern.finditer(block_content):
        # 计算块内指令相对于起始行的行号
        relative_lines = block_content[:match.start()].count('\n')
        current_line = start_line + relative_lines

        full_cmd = match.group('instruction')
        if full_cmd.startswith('ROTATE'):
            direction = match.group(2)
            print(f"第{current_line}行(重复执行):旋转{direction}")
            # robot.rotate(direction)
        elif full_cmd.startswith('GO'):
            units = int(match.group(5))
            print(f"第{current_line}行(重复执行):移动{units}单位")
            # robot.go(units)
        elif full_cmd == 'DRILL':
            print(f"第{current_line}行(重复执行):钻孔")
            # robot.drill()
        elif full_cmd.startswith('REPEAT'):
            repeat_times = int(match.group(6))
            nested_block = match.group('block')
            print(f"第{current_line}行(重复执行):嵌套重复{repeat_times}次")
            # 递归处理嵌套REPEAT
            process_repeat_block(nested_block, current_line)

3. 关键注意事项

  • 自然数匹配:正则中用[1-9]\d*确保N是大于0的自然数,若允许0可改为\d+。
  • 空白处理:所有指令间的分隔用\s*,兼容单行多指令、跨多行指令的场景。
  • 递归深度限制:Python正则的递归深度有限(默认约100层),若你的指令嵌套层数极深,可能需要改用PEG解析器(如parsimonious),但常规场景下递归正则足够用。
  • 语法错误定位:通过检查未匹配的内容,能精准定位无效指令的行号,满足需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:22:35