基于Python的数控代码变量替换与简化技术

引言

在现代数控加工领域,数控编程语言常常包含变量和表达式,这为参数化编程提供了极大的灵活性。然而,在实际加工过程中,通常需要将参数化程序转换为具体的数值程序。本文将详细介绍如何使用Python处理包含变量的数控代码文件,实现变量替换和代码简化。

问题分析

数控代码中的变量通常以@符号开头,如@1107@1017等。这些变量可能用于表示刀具半径补偿、加工深度等参数。变量之间可能存在依赖关系,例如:

@1017:=0.6427876096865394×@1107@1017: = 0.6427876096865394 × @1107@1017:=0.6427876096865394×@1107

@1018:=−0.766044443118978×@1107@1018: = -0.766044443118978 × @1107@1018:=0.766044443118978×@1107

@1144:=8.21951+@1017@1144: = 8.21951 + @1017@1144:=8.21951+@1017

@1145:=94.79563+@1018@1145: = 94.79563 + @1018@1145:=94.79563+@1018

程序执行时,需要根据给定的@1107值计算所有相关变量,并将所有变量引用替换为具体数值,最终生成可直接执行的G代码。

解决方案设计

1. 基本思路

处理这类问题的核心思想是:

  1. 解析数控代码文件,识别变量赋值语句和变量引用
  2. 建立变量间的依赖关系,按顺序计算变量值
  3. 将代码中的变量引用替换为计算后的数值
  4. 清理变量赋值语句,生成简洁的G代码

2. 关键技术点

  • 变量识别:使用正则表达式匹配变量格式
  • 表达式计算:安全地计算包含变量的数学表达式
  • 依赖关系处理:确保变量按正确顺序计算
  • 代码简化:移除冗余的变量赋值语句

完整代码实现

版本1:基础处理框架

"""
数控代码变量替换处理框架
功能:读取包含变量的数控代码,替换所有变量为具体数值
作者:数控编程助手
版本:1.0
"""

import re
import os

class NcVariableProcessor:
    """数控代码变量处理器"""
    
    def __init__(self):
        """初始化处理器"""
        self.variables = {}  # 存储变量值的字典
        self.assignment_pattern = re.compile(r'@(\d+):\s*=\s*(.+);')  # 匹配变量赋值
        self.var_ref_pattern = re.compile(r'@(\d+)')  # 匹配变量引用
        
    def set_variable(self, var_name, value):
        """设置变量值
        
        Args:
            var_name: 变量名(不带@符号)
            value: 变量值
        """
        self.variables[str(var_name)] = float(value)
    
    def compute_expression(self, expression):
        """计算数学表达式
        
        Args:
            expression: 包含变量引用的表达式字符串
            
        Returns:
            float: 计算结果
        """
        # 替换表达式中的变量引用
        def replace_var(match):
            var_name = match.group(1)
            if var_name in self.variables:
                return str(self.variables[var_name])
            else:
                raise ValueError(f"未定义的变量: @{var_name}")
        
        # 替换所有变量引用
        expr = self.var_ref_pattern.sub(replace_var, expression)
        
        try:
            # 安全计算表达式
            result = eval(expr, {"__builtins__": {}}, {})
            return float(result)
        except Exception as e:
            raise ValueError(f"表达式计算错误: {expression} -> {e}")
    
    def process_line(self, line):
        """处理单行代码
        
        Args:
            line: 输入行字符串
            
        Returns:
            tuple: (处理后的行, 是否输出该行)
        """
        line = line.rstrip()
        
        # 跳过空行和注释
        if not line or line.startswith('%'):
            return line, True
        
        # 检查是否是变量赋值语句
        match = self.assignment_pattern.match(line)
        if match:
            var_name = match.group(1)
            expression = match.group(2)
            
            try:
                # 计算变量值
                value = self.compute_expression(expression)
                self.variables[var_name] = value
                return None, False  # 不输出赋值语句
            except ValueError as e:
                print(f"警告: {e}")
                return line, True
        
        # 处理非赋值语句,替换变量引用
        def replace_in_code(match):
            var_name = match.group(1)
            if var_name in self.variables:
                return f"{self.variables[var_name]:.5f}"
            else:
                return match.group(0)  # 保持原样
        
        processed_line = self.var_ref_pattern.sub(replace_in_code, line)
        return processed_line, True
    
    def process_file(self, input_file, output_file, initial_vars=None):
        """处理整个文件
        
        Args:
            input_file: 输入文件名
            output_file: 输出文件名
            initial_vars: 初始变量字典 {变量名: 值}
        """
        # 初始化变量
        if initial_vars:
            for var_name, value in initial_vars.items():
                self.set_variable(var_name, value)
        
        # 读取文件
        try:
            with open(input_file, 'r', encoding='utf-8') as f:
                lines = f.readlines()
        except UnicodeDecodeError:
            with open(input_file, 'r', encoding='gbk') as f:
                lines = f.readlines()
        
        # 处理每一行
        processed_lines = []
        for i, line in enumerate(lines, 1):
            try:
                processed_line, should_output = self.process_line(line)
                if should_output and processed_line is not None:
                    processed_lines.append(processed_line)
            except Exception as e:
                print(f"第{i}行处理错误: {e}")
                processed_lines.append(line)  # 保持原行
        
        # 写入输出文件
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write('\n'.join(processed_lines))
        
        print(f"处理完成: {input_file} -> {output_file}")
        print(f"处理的变量数: {len(self.variables)}")

# 使用示例
if __name__ == "__main__":
    # 创建处理器
    processor = NcVariableProcessor()
    
    # 设置初始变量(例如@1107的值)
    processor.set_variable('1107', 10.0)
    
    # 处理文件
    input_file = "01001.txt"
    output_file = "processed_nc.txt"
    
    if os.path.exists(input_file):
        processor.process_file(input_file, output_file)
        
        # 显示变量计算结果
        print("\n变量计算结果:")
        for var_name, value in sorted(processor.variables.items()):
            print(f"  @{var_name} = {value:.10f}")
    else:
        print(f"文件不存在: {input_file}")

版本2:增强型变量处理器

"""
增强型数控代码变量处理器
功能:支持更复杂的表达式和批量处理
版本:2.0
"""

import re
import os
import math

class EnhancedNcProcessor:
    """增强型数控代码处理器"""
    
    def __init__(self):
        """初始化处理器"""
        self.variables = {}
        self.lines_processed = 0
        self.errors = []
        
        # 编译正则表达式
        self.assign_regex = re.compile(r'@(\d+):\s*=\s*(.+?)(?=;|$)')
        self.var_regex = re.compile(r'@(\d+)')
        
        # 支持的数学函数
        self.safe_dict = {
            'sin': math.sin, 'cos': math.cos, 'tan': math.tan,
            'asin': math.asin, 'acos': math.acos, 'atan': math.atan,
            'sqrt': math.sqrt, 'exp': math.exp, 'log': math.log,
            'log10': math.log10, 'pi': math.pi, 'e': math.e,
            'abs': abs, 'round': round, 'int': int, 'float': float
        }
    
    def add_variable(self, name, value):
        """添加或修改变量
        
        Args:
            name: 变量名
            value: 变量值
        """
        self.variables[str(name)] = float(value)
    
    def evaluate_expression(self, expr):
        """安全地计算表达式
        
        Args:
            expr: 表达式字符串
            
        Returns:
            float: 计算结果
        """
        # 替换变量引用
        def replace_var(match):
            var_name = match.group(1)
            if var_name in self.variables:
                return str(self.variables[var_name])
            raise NameError(f"变量 @{var_name} 未定义")
        
        # 替换所有变量引用
        while True:
            new_expr = self.var_regex.sub(replace_var, expr)
            if new_expr == expr:
                break
            expr = new_expr
        
        try:
            # 安全计算
            result = eval(expr, {"__builtins__": None}, self.safe_dict)
            return float(result)
        except Exception as e:
            raise ValueError(f"表达式 '{expr}' 计算失败: {e}")
    
    def parse_assignments(self, line):
        """解析行中的赋值语句
        
        Args:
            line: 输入行
            
        Returns:
            tuple: (非赋值部分, 赋值语句列表)
        """
        assignments = []
        remaining = line
        
        # 查找所有赋值语句
        pos = 0
        while True:
            match = self.assign_regex.search(remaining[pos:])
            if not match:
                break
            
            # 提取赋值语句
            full_match = match.group(0)
            var_name = match.group(1)
            expression = match.group(2).strip()
            
            assignments.append((var_name, expression))
            
            # 更新位置
            pos += match.end()
            
            # 如果后面是分号,跳过
            if pos < len(remaining) and remaining[pos] == ';':
                pos += 1
        
        # 获取非赋值部分
        non_assign = remaining[pos:] if pos < len(remaining) else ''
        
        return non_assign.strip(), assignments
    
    def process_single_line(self, line):
        """处理单行代码
        
        Args:
            line: 输入行
            
        Returns:
            str: 处理后的行
        """
        self.lines_processed += 1
        
        # 移除首尾空白
        line = line.strip()
        
        # 处理特殊行
        if not line or line.startswith('%') or line.startswith('('):
            return line
        
        # 解析赋值语句
        non_assign_part, assignments = self.parse_assignments(line)
        
        # 处理赋值语句
        for var_name, expression in assignments:
            try:
                value = self.evaluate_expression(expression)
                self.add_variable(var_name, value)
            except Exception as e:
                self.errors.append(f"第{self.lines_processed}行: @{var_name}赋值失败 - {e}")
        
        # 替换非赋值部分中的变量引用
        def replace_vars_in_text(text):
            def repl(match):
                var_name = match.group(1)
                if var_name in self.variables:
                    # 根据上下文决定精度
                    if 'G00' in text or 'G01' in text:
                        return f"{self.variables[var_name]:.5f}"
                    else:
                        return f"{self.variables[var_name]}"
                return match.group(0)
            
            return self.var_regex.sub(repl, text)
        
        # 处理非赋值部分
        processed_non_assign = replace_vars_in_text(non_assign_part)
        
        # 清理多余的分号
        if processed_non_assign.endswith(';'):
            processed_non_assign = processed_non_assign.rstrip(';')
        
        return processed_non_assign
    
    def batch_process(self, input_files, output_dir, initial_vars=None):
        """批量处理多个文件
        
        Args:
            input_files: 输入文件列表
            output_dir: 输出目录
            initial_vars: 初始变量字典
        """
        # 创建输出目录
        os.makedirs(output_dir, exist_ok=True)
        
        # 设置初始变量
        if initial_vars:
            for name, value in initial_vars.items():
                self.add_variable(name, value)
        
        results = []
        for input_file in input_files:
            if not os.path.exists(input_file):
                print(f"警告: 文件不存在 {input_file}")
                continue
            
            # 重置处理器状态(保留初始变量)
            current_vars = self.variables.copy()
            self.variables = initial_vars.copy() if initial_vars else {}
            self.errors = []
            
            # 处理文件
            output_file = os.path.join(output_dir, f"proc_{os.path.basename(input_file)}")
            
            with open(input_file, 'r', encoding='utf-8') as f:
                input_lines = f.readlines()
            
            output_lines = []
            for line in input_lines:
                processed = self.process_single_line(line)
                if processed:  # 只添加非空行
                    output_lines.append(processed)
            
            # 写入输出文件
            with open(output_file, 'w', encoding='utf-8') as f:
                f.write('\n'.join(output_lines))
            
            # 恢复变量
            self.variables = current_vars
            
            # 记录结果
            results.append({
                'input': input_file,
                'output': output_file,
                'lines': len(output_lines),
                'variables': len(self.variables),
                'errors': self.errors.copy()
            })
            
            print(f"✓ 已处理: {input_file} -> {output_file}")
        
        return results

# 使用示例
if __name__ == "__main__":
    # 创建处理器
    processor = EnhancedNcProcessor()
    
    # 设置初始变量
    initial_variables = {
        '1107': 5.0,  # 示例值
        '1001': 10.0, # 可以设置多个初始变量
    }
    
    # 要处理的文件列表
    input_files = ["01001.txt", "01002.txt"]  # 假设有多个文件
    
    # 批量处理
    output_dir = "processed_files"
    results = processor.batch_process(input_files, output_dir, initial_variables)
    
    # 显示处理结果
    print(f"\n处理完成!共处理 {len(results)} 个文件")
    print(f"输出目录: {output_dir}")
    
    # 显示汇总信息
    total_errors = sum(len(r['errors']) for r in results)
    if total_errors > 0:
        print(f"\n发现 {total_errors} 个错误:")
        for result in results:
            for error in result['errors']:
                print(f"  {error}")
    else:
        print("\n所有文件处理成功,无错误!")

版本3:优化版G代码生成器

"""
优化版G代码生成器
功能:生成简洁、格式化的G代码
版本:3.0
"""

import re
import os
from datetime import datetime

class GCodeOptimizer:
    """G代码优化器"""
    
    def __init__(self, precision=5):
        """初始化优化器
        
        Args:
            precision: 数值精度(小数位数)
        """
        self.precision = precision
        self.variables = {}
        self.macro_definitions = {}
        
        # 编译正则表达式
        self.macro_pattern = re.compile(r'%\s*@MACRO\s*;', re.IGNORECASE)
        self.assign_pattern = re.compile(r'@(\d+)\s*:\s*=\s*(.+?)\s*(;|$)')
        self.var_pattern = re.compile(r'@(\d+)')
        self.gcode_pattern = re.compile(r'([GXYZABCUF]\s*[-]?\d*\.?\d+)', re.IGNORECASE)
        
    def set_variable(self, name, value):
        """设置变量值
        
        Args:
            name: 变量名
            value: 变量值
        """
        self.variables[str(name)] = float(value)
    
    def format_number(self, number):
        """格式化数字
        
        Args:
            number: 输入数字
            
        Returns:
            str: 格式化后的字符串
        """
        return f"{float(number):.{self.precision}f}".rstrip('0').rstrip('.')
    
    def evaluate_expression(self, expression):
        """计算表达式
        
        Args:
            expression: 表达式字符串
            
        Returns:
            float: 计算结果
        """
        # 替换变量引用
        def replace_match(match):
            var_name = match.group(1)
            if var_name in self.variables:
                return str(self.variables[var_name])
            return match.group(0)
        
        expr = self.var_pattern.sub(replace_match, expression)
        
        try:
            # 安全计算
            result = eval(expr, {"__builtins__": {}}, {})
            return float(result)
        except Exception as e:
            raise ValueError(f"表达式错误: {expression} -> {e}")
    
    def parse_line(self, line):
        """解析行内容
        
        Args:
            line: 输入行
            
        Returns:
            dict: 解析结果
        """
        line = line.strip()
        
        result = {
            'original': line,
            'is_macro': False,
            'is_comment': False,
            'is_assignment': False,
            'is_gcode': False,
            'assignments': [],
            'gcode_commands': [],
            'processed': line
        }
        
        # 检查宏定义
        if self.macro_pattern.match(line):
            result['is_macro'] = True
            result['processed'] = f"% MACRO PROCESSED AT {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
            return result
        
        # 检查注释
        if line.startswith('%') or line.startswith('(') or line.startswith(';'):
            result['is_comment'] = True
            return result
        
        # 检查赋值语句
        assignments = []
        remaining = line
        
        # 查找所有赋值语句
        while True:
            match = self.assign_pattern.search(remaining)
            if not match:
                break
            
            var_name = match.group(1)
            expression = match.group(2)
            
            assignments.append({
                'var_name': var_name,
                'expression': expression,
                'full_match': match.group(0)
            })
            
            # 移除已匹配的部分
            remaining = remaining[:match.start()] + remaining[match.end():]
        
        if assignments:
            result['is_assignment'] = True
            result['assignments'] = assignments
        
        # 检查G代码
        gcode_matches = list(self.gcode_pattern.finditer(remaining))
        if gcode_matches:
            result['is_gcode'] = True
            result['gcode_commands'] = [m.group(1) for m in gcode_matches]
        
        # 处理剩余部分(可能包含变量引用)
        if remaining.strip():
            # 替换变量引用
            def replace_vars(match):
                var_name = match.group(1)
                if var_name in self.variables:
                    return self.format_number(self.variables[var_name])
                return match.group(0)
            
            processed = self.var_pattern.sub(replace_vars, remaining)
            result['processed'] = processed.strip()
        
        return result
    
    def optimize_gcode_block(self, commands):
        """优化G代码块
        
        Args:
            commands: G代码命令列表
            
        Returns:
            str: 优化后的G代码行
        """
        if not commands:
            return ""
        
        # 按字母排序并合并
        grouped = {}
        for cmd in commands:
            # 提取命令字母和值
            letter = cmd[0].upper()
            value = cmd[1:].strip()
            
            # 保留原始值,格式化在最后进行
            grouped[letter] = value
        
        # 构建优化后的字符串
        # G命令放在最前面
        ordered_keys = []
        if 'G' in grouped:
            ordered_keys.append('G')
        
        # 然后是运动坐标
        for axis in ['X', 'Y', 'Z', 'A', 'B', 'C']:
            if axis in grouped:
                ordered_keys.append(axis)
        
        # 最后是其他参数
        for key in sorted(grouped.keys()):
            if key not in ordered_keys:
                ordered_keys.append(key)
        
        # 生成优化后的命令
        optimized_parts = []
        for key in ordered_keys:
            try:
                value = float(grouped[key])
                formatted = self.format_number(value)
                optimized_parts.append(f"{key}{formatted}")
            except:
                optimized_parts.append(f"{key}{grouped[key]}")
        
        return ' '.join(optimized_parts)
    
    def process_file(self, input_file, output_file, initial_vars=None):
        """处理文件
        
        Args:
            input_file: 输入文件
            output_file: 输出文件
            initial_vars: 初始变量
        """
        # 设置初始变量
        if initial_vars:
            for name, value in initial_vars.items():
                self.set_variable(name, value)
        
        # 读取文件
        try:
            with open(input_file, 'r', encoding='utf-8') as f:
                lines = f.readlines()
        except:
            with open(input_file, 'r', encoding='gbk') as f:
                lines = f.readlines()
        
        # 处理每一行
        processed_lines = []
        line_stats = {
            'total': 0,
            'comments': 0,
            'assignments': 0,
            'gcode': 0,
            'macros': 0,
            'errors': 0
        }
        
        for line_num, line in enumerate(lines, 1):
            line_stats['total'] += 1
            
            try:
                # 解析行
                parsed = self.parse_line(line)
                
                # 处理赋值语句
                if parsed['is_assignment']:
                    line_stats['assignments'] += 1
                    for assign in parsed['assignments']:
                        try:
                            value = self.evaluate_expression(assign['expression'])
                            self.set_variable(assign['var_name'], value)
                        except Exception as e:
                            print(f"第{line_num}行警告: {e}")
                            line_stats['errors'] += 1
                
                # 处理G代码
                elif parsed['is_gcode']:
                    line_stats['gcode'] += 1
                    
                    # 如果有G代码命令,进行优化
                    if parsed['gcode_commands']:
                        optimized = self.optimize_gcode_block(parsed['gcode_commands'])
                        
                        # 如果有其他内容,添加到优化后的G代码后面
                        other_content = parsed['processed']
                        if other_content and not other_content.startswith(tuple('GXYZABC')):
                            if optimized:
                                processed_line = f"{optimized} ; {other_content}"
                            else:
                                processed_line = other_content
                        else:
                            processed_line = optimized if optimized else other_content
                        
                        if processed_line:
                            processed_lines.append(processed_line)
                
                # 处理宏和注释
                elif parsed['is_macro']:
                    line_stats['macros'] += 1
                    processed_lines.append(parsed['processed'])
                elif parsed['is_comment']:
                    line_stats['comments'] += 1
                    processed_lines.append(parsed['original'])
                else:
                    # 其他内容
                    if parsed['processed']:
                        processed_lines.append(parsed['processed'])
            
            except Exception as e:
                print(f"第{line_num}行错误: {e}")
                processed_lines.append(line)  # 保持原行
                line_stats['errors'] += 1
        
        # 添加文件头注释
        header = [
            f"% Generated by GCodeOptimizer v3.0",
            f"% Source: {os.path.basename(input_file)}",
            f"% Processed: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            f"% Variables used: {len(self.variables)}",
            f"% Precision: {self.precision} decimal places",
            f"%"
        ]
        
        # 写入输出文件
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write('\n'.join(header + [''] + processed_lines))
        
        # 显示统计信息
        print(f"\n=== 处理统计 ===")
        print(f"输入文件: {input_file}")
        print(f"输出文件: {output_file}")
        print(f"总行数: {line_stats['total']}")
        print(f"G代码行: {line_stats['gcode']}")
        print(f"赋值语句: {line_stats['assignments']}")
        print(f"注释/宏: {line_stats['comments'] + line_stats['macros']}")
        print(f"错误数: {line_stats['errors']}")
        print(f"压缩率: {(1 - len(processed_lines)/line_stats['total'])*100:.1f}%")
        
        return {
            'stats': line_stats,
            'variables': self.variables,
            'output_file': output_file
        }

# 使用示例
if __name__ == "__main__":
    # 创建优化器
    optimizer = GCodeOptimizer(precision=5)
    
    # 设置初始变量
    initial_vars = {'1107': 15.5}  # 可根据需要修改
    
    # 输入输出文件
    input_file = "01001.txt"
    output_file = "optimized_nc.txt"
    
    if os.path.exists(input_file):
        # 处理文件
        result = optimizer.process_file(input_file, output_file, initial_vars)
        
        # 显示变量值
        print(f"\n=== 变量值 ===")
        for var_name, value in sorted(result['variables'].items()):
            print(f"@{var_name} = {value:.{optimizer.precision}f}")
        
        # 显示输出文件前10行
        print(f"\n=== 输出文件预览 ===")
        with open(output_file, 'r') as f:
            for i in range(10):
                line = f.readline()
                if not line:
                    break
                print(line.rstrip())
    else:
        print(f"输入文件不存在: {input_file}")

版本4:完整应用示例

"""
数控代码批量处理工具
功能:完整的数控代码处理流水线
版本:4.0
"""

import os
import sys
import json
import logging
from datetime import datetime

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('nc_processor.log'),
        logging.StreamHandler(sys.stdout)
    ]
)

class NcProcessingPipeline:
    """数控代码处理流水线"""
    
    def __init__(self, config_file=None):
        """初始化流水线
        
        Args:
            config_file: 配置文件路径
        """
        self.config = self.load_config(config_file)
        self.processors = []
        self.results = []
        
        # 设置默认配置
        self.default_config = {
            'precision': 5,
            'remove_comments': False,
            'optimize_gcode': True,
            'output_format': 'txt',
            'backup_original': True,
            'log_level': 'INFO'
        }
        
        if self.config:
            self.default_config.update(self.config)
        
        self.config = self.default_config
        
        logging.info(f"数控代码处理流水线已初始化,配置: {self.config}")
    
    def load_config(self, config_file):
        """加载配置文件
        
        Args:
            config_file: 配置文件路径
            
        Returns:
            dict: 配置字典
        """
        if config_file and os.path.exists(config_file):
            try:
                with open(config_file, 'r') as f:
                    return json.load(f)
            except Exception as e:
                logging.error(f"配置文件加载失败: {e}")
                return {}
        return {}
    
    def validate_input_file(self, file_path):
        """验证输入文件
        
        Args:
            file_path: 文件路径
            
        Returns:
            bool: 是否有效
        """
        if not os.path.exists(file_path):
            logging.error(f"文件不存在: {file_path}")
            return False
        
        if not file_path.lower().endswith(('.txt', '.nc', '.cnc')):
            logging.warning(f"文件扩展名可能不受支持: {file_path}")
        
        # 检查文件大小(不超过10MB)
        if os.path.getsize(file_path) > 10 * 1024 * 1024:
            logging.error(f"文件过大: {file_path}")
            return False
        
        return True
    
    def parse_variable_assignments(self, content):
        """解析变量赋值语句
        
        Args:
            content: 文件内容
            
        Returns:
            dict: 变量依赖关系
        """
        import re
        
        # 匹配变量赋值
        pattern = re.compile(r'@(\d+)\s*:\s*=\s*(.+?)(?=;|\n|$)')
        assignments = {}
        
        for match in pattern.finditer(content):
            var_name = match.group(1)
            expression = match.group(2).strip()
            
            # 提取依赖的变量
            deps = re.findall(r'@(\d+)', expression)
            
            assignments[var_name] = {
                'expression': expression,
                'dependencies': list(set(deps)),
                'computed': False,
                'value': None
            }
        
        return assignments
    
    def compute_variable_values(self, assignments, initial_values):
        """计算变量值
        
        Args:
            assignments: 变量赋值字典
            initial_values: 初始变量值
            
        Returns:
            dict: 计算后的变量值
        """
        import re
        
        # 初始化变量值
        computed = {}
        computed.update(initial_values)
        
        # 标记已计算的变量
        for var_name in initial_values:
            if var_name in assignments:
                assignments[var_name]['computed'] = True
                assignments[var_name]['value'] = initial_values[var_name]
        
        # 计算顺序
        max_iterations = len(assignments) * 2  # 防止无限循环
        iteration = 0
        
        while iteration < max_iterations:
            iteration += 1
            progress = False
            
            for var_name, info in assignments.items():
                if info['computed']:
                    continue
                
                # 检查依赖是否都已计算
                deps_computed = all(dep in computed for dep in info['dependencies'])
                
                if deps_computed:
                    try:
                        # 替换表达式中的变量引用
                        expression = info['expression']
                        for dep in info['dependencies']:
                            expression = expression.replace(f'@{dep}', str(computed[dep]))
                        
                        # 计算表达式
                        value = eval(expression, {"__builtins__": {}}, {})
                        computed[var_name] = float(value)
                        info['computed'] = True
                        info['value'] = value
                        progress = True
                        
                        logging.debug(f"计算变量 @{var_name} = {expression} = {value}")
                    except Exception as e:
                        logging.error(f"变量 @{var_name} 计算失败: {e}")
                        # 使用默认值0
                        computed[var_name] = 0.0
                        info['computed'] = True
                        info['value'] = 0.0
                        progress = True
            
            if not progress:
                break
        
        # 检查未计算的变量
        for var_name, info in assignments.items():
            if not info['computed']:
                logging.warning(f"变量 @{var_name} 未计算,使用默认值0")
                computed[var_name] = 0.0
        
        return computed
    
    def process_single_file(self, input_file, output_file=None, initial_values=None):
        """处理单个文件
        
        Args:
            input_file: 输入文件
            output_file: 输出文件
            initial_values: 初始变量值
            
        Returns:
            dict: 处理结果
        """
        start_time = datetime.now()
        
        # 验证文件
        if not self.validate_input_file(input_file):
            return {
                'status': 'error',
                'message': f'文件验证失败: {input_file}'
            }
        
        # 默认输出文件名
        if not output_file:
            base_name = os.path.splitext(os.path.basename(input_file))[0]
            output_file = f"{base_name}_processed.{self.config['output_format']}"
        
        # 备份原文件
        if self.config['backup_original']:
            backup_file = f"{input_file}.backup"
            try:
                import shutil
                shutil.copy2(input_file, backup_file)
                logging.info(f"已备份原文件: {backup_file}")
            except Exception as e:
                logging.warning(f"文件备份失败: {e}")
        
        try:
            # 读取文件
            with open(input_file, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 解析变量赋值
            assignments = self.parse_variable_assignments(content)
            logging.info(f"解析到 {len(assignments)} 个变量赋值")
            
            # 计算变量值
            initial_values = initial_values or {}
            computed_values = self.compute_variable_values(assignments, initial_values)
            logging.info(f"计算了 {len(computed_values)} 个变量值")
            
            # 替换变量引用
            import re
            var_pattern = re.compile(r'@(\d+)')
            
            def replace_var(match):
                var_name = match.group(1)
                if var_name in computed_values:
                    value = computed_values[var_name]
                    # 根据精度格式化
                    return f"{value:.{self.config['precision']}f}"
                return match.group(0)
            
            # 替换所有变量引用
            processed_content = var_pattern.sub(replace_var, content)
            
            # 移除变量赋值语句(可选)
            if self.config.get('remove_assignments', True):
                assignment_pattern = re.compile(r'@\d+\s*:\s*=.*?(?=;|\n|$);?')
                processed_content = assignment_pattern.sub('', processed_content)
            
            # 移除注释(可选)
            if self.config.get('remove_comments', False):
                # 移除%注释
                processed_content = re.sub(r'%.*?(?=\n|$)', '', processed_content)
                # 移除()注释
                processed_content = re.sub(r'\(.*?\)', '', processed_content)
            
            # 优化G代码格式
            if self.config.get('optimize_gcode', True):
                # 合并多空格
                processed_content = re.sub(r'\s+', ' ', processed_content)
                # 清理多余的分号
                processed_content = re.sub(r';\s*;', ';', processed_content)
                # 移除空行
                lines = processed_content.split('\n')
                processed_lines = [line.strip() for line in lines if line.strip()]
                processed_content = '\n'.join(processed_lines)
            
            # 写入输出文件
            with open(output_file, 'w', encoding='utf-8') as f:
                f.write(processed_content)
            
            # 计算处理时间
            end_time = datetime.now()
            duration = (end_time - start_time).total_seconds()
            
            # 收集结果
            result = {
                'status': 'success',
                'input_file': input_file,
                'output_file': output_file,
                'original_size': len(content),
                'processed_size': len(processed_content),
                'variables_found': len(assignments),
                'variables_computed': len(computed_values),
                'processing_time': duration,
                'compression_ratio': (1 - len(processed_content)/len(content)) * 100,
                'timestamp': end_time.isoformat()
            }
            
            logging.info(f"文件处理完成: {input_file} -> {output_file}")
            logging.info(f"处理统计: {result}")
            
            return result
            
        except Exception as e:
            logging.error(f"文件处理失败 {input_file}: {e}")
            return {
                'status': 'error',
                'message': str(e),
                'input_file': input_file
            }
    
    def process_batch(self, input_files, output_dir=None, initial_values=None):
        """批量处理文件
        
        Args:
            input_files: 输入文件列表
            output_dir: 输出目录
            initial_values: 初始变量值
            
        Returns:
            list: 处理结果列表
        """
        results = []
        
        # 创建输出目录
        if output_dir:
            os.makedirs(output_dir, exist_ok=True)
        
        total_files = len(input_files)
        successful = 0
        failed = 0
        
        logging.info(f"开始批量处理 {total_files} 个文件")
        
        for i, input_file in enumerate(input_files, 1):
            logging.info(f"处理文件 {i}/{total_files}: {input_file}")
            
            # 确定输出文件路径
            if output_dir:
                base_name = os.path.basename(input_file)
                output_file = os.path.join(output_dir, f"proc_{base_name}")
            else:
                output_file = None
            
            # 处理文件
            result = self.process_single_file(input_file, output_file, initial_values)
            
            # 更新统计
            if result['status'] == 'success':
                successful += 1
            else:
                failed += 1
            
            results.append(result)
            
            # 显示进度
            progress = (i / total_files) * 100
            logging.info(f"进度: {progress:.1f}% | 成功: {successful} | 失败: {failed}")
        
        # 生成汇总报告
        summary = {
            'total_files': total_files,
            'successful': successful,
            'failed': failed,
            'success_rate': (successful / total_files * 100) if total_files > 0 else 0,
            'total_processing_time': sum(r.get('processing_time', 0) for r in results if r['status'] == 'success'),
            'average_compression': sum(r.get('compression_ratio', 0) for r in results if r['status'] == 'success') / successful if successful > 0 else 0,
            'timestamp': datetime.now().isoformat()
        }
        
        logging.info(f"批量处理完成,汇总: {summary}")
        
        # 保存结果到JSON文件
        report_file = f"processing_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(report_file, 'w') as f:
            json.dump({
                'config': self.config,
                'summary': summary,
                'results': results
            }, f, indent=2)
        
        logging.info(f"详细报告已保存到: {report_file}")
        
        return results, summary
    
    def generate_variable_report(self, input_file):
        """生成变量分析报告
        
        Args:
            input_file: 输入文件
            
        Returns:
            dict: 变量报告
        """
        if not self.validate_input_file(input_file):
            return None
        
        try:
            with open(input_file, 'r') as f:
                content = f.read()
            
            # 解析变量
            assignments = self.parse_variable_assignments(content)
            
            # 提取所有变量引用
            import re
            all_var_refs = re.findall(r'@(\d+)', content)
            var_usage = {}
            
            for var in set(all_var_refs):
                var_usage[var] = all_var_refs.count(var)
            
            # 分析变量类型
            numeric_vars = []
            expression_vars = []
            
            for var_name, info in assignments.items():
                if re.match(r'^[-+]?\d*\.?\d+$', info['expression'].strip()):
                    numeric_vars.append(var_name)
                else:
                    expression_vars.append(var_name)
            
            # 构建报告
            report = {
                'file': input_file,
                'total_variables': len(set(all_var_refs)),
                'variable_assignments': len(assignments),
                'variable_usage': var_usage,
                'numeric_variables': numeric_vars,
                'expression_variables': expression_vars,
                'dependency_depth': self.calculate_dependency_depth(assignments),
                'recommendations': self.generate_recommendations(assignments, var_usage)
            }
            
            return report
            
        except Exception as e:
            logging.error(f"变量分析失败: {e}")
            return None
    
    def calculate_dependency_depth(self, assignments):
        """计算变量依赖深度
        
        Args:
            assignments: 变量赋值字典
            
        Returns:
            dict: 每个变量的依赖深度
        """
        depths = {}
        
        def get_depth(var_name, visited=None):
            if visited is None:
                visited = set()
            
            if var_name in visited:
                return 0  # 循环依赖
            
            if var_name not in assignments:
                return 0
            
            if var_name in depths:
                return depths[var_name]
            
            visited.add(var_name)
            max_depth = 0
            
            for dep in assignments[var_name]['dependencies']:
                depth = get_depth(dep, visited.copy())
                max_depth = max(max_depth, depth)
            
            depths[var_name] = max_depth + 1
            return depths[var_name]
        
        for var_name in assignments:
            get_depth(var_name)
        
        return depths
    
    def generate_recommendations(self, assignments, var_usage):
        """生成优化建议
        
        Args:
            assignments: 变量赋值
            var_usage: 变量使用统计
            
        Returns:
            list: 建议列表
        """
        recommendations = []
        
        # 检查未使用的变量
        for var_name in assignments:
            if var_name not in var_usage or var_usage[var_name] <= 1:
                recommendations.append(f"变量 @{var_name} 使用次数少,考虑内联或删除")
        
        # 检查简单表达式
        import re
        for var_name, info in assignments.items():
            if len(info['dependencies']) == 0 and re.match(r'^[-+]?\d*\.?\d+$', info['expression']):
                recommendations.append(f"变量 @{var_name} 为常量,可直接替换为 {info['expression']}")
        
        # 检查复杂依赖
        depths = self.calculate_dependency_depth(assignments)
        for var_name, depth in depths.items():
            if depth > 3:
                recommendations.append(f"变量 @{var_name} 依赖链深度为 {depth},考虑简化")
        
        return recommendations

# 主程序入口
def main():
    """主函数"""
    print("=" * 60)
    print("数控代码变量处理工具 v4.0")
    print("=" * 60)
    
    # 创建流水线
    pipeline = NcProcessingPipeline()
    
    # 示例:处理单个文件
    input_file = "01001.txt"
    
    if os.path.exists(input_file):
        print(f"\n1. 分析文件: {input_file}")
        
        # 生成变量报告
        report = pipeline.generate_variable_report(input_file)
        if report:
            print(f"   发现 {report['total_variables']} 个变量")
            print(f"   变量赋值语句: {report['variable_assignments']}")
            print(f"   建议: {len(report['recommendations'])} 条")
            
            # 显示前5个最常用的变量
            sorted_usage = sorted(report['variable_usage'].items(), 
                                 key=lambda x: x[1], reverse=True)[:5]
            print(f"   最常用的变量:")
            for var, count in sorted_usage:
                print(f"     @{var}: 使用 {count} 次")
        
        print(f"\n2. 处理文件")
        
        # 设置初始变量值
        initial_values = {'1107': 10.0}  # 根据实际情况修改
        
        # 处理文件
        result = pipeline.process_single_file(
            input_file=input_file,
            output_file="processed_output.txt",
            initial_values=initial_values
        )
        
        if result['status'] == 'success':
            print(f"   处理成功!")
            print(f"   输出文件: {result['output_file']}")
            print(f"   处理时间: {result['processing_time']:.2f}秒")
            print(f"   压缩率: {result['compression_ratio']:.1f}%")
        else:
            print(f"   处理失败: {result['message']}")
    
    else:
        print(f"\n文件 {input_file} 不存在")
        print("\n创建示例文件...")
        
        # 创建示例文件
        example_content = """% 示例数控代码
G58;
G90 G00 B-50.00000;
@1017: = 0.6427876096865394*@1107;
@1018: = -0.766044443118978*@1107;
@1144: = 8.21951 + @1017;
@1145: = 94.79563 + @1018;
G00 Z@1145;
G00 X@1144;
G00 Y60.12500;
G00 C0.00000;
G01 Y50.12500 X@1144 Z@1145 C0.00000 F1000.0;"""
        
        with open("example_nc.txt", "w") as f:
            f.write(example_content)
        
        print("已创建 example_nc.txt 文件")
    
    print("\n" + "=" * 60)
    print("处理完成!")
    print("=" * 60)

if __name__ == "__main__":
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值