侧边栏壁纸
博主头像
分享你我博主等级

行动起来,活在当下

  • 累计撰写 114 篇文章
  • 累计创建 13 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

js解析sh文件

管理员
2025-03-09 / 0 评论 / 0 点赞 / 7 阅读 / 9581 字
class ShellParser {
    constructor() {
        this.variables = {};  // 普通变量
        this.exports = {};    // 导出变量
        this.sections = [];   // 所有section
        this.comments = [];   // 所有注释
        this.originalContent = ''; // 原始内容
    }

    // 解析整个shell文件
    parseFile(content) {
        this.originalContent = content;
        const lines = content.split('\n');
        
        let currentSection = {
            name: '',
            level: 0,
            lineNumber: 0,
            variables: [],
            comments: []
        };
        this.sections.push(currentSection);
        
        let currentSectionContent = '';  // 用于收集section的内容
        let lastComment = null;
        let inMultilineValue = false;
        let currentVariable = null;
        let multilineBuffer = [];

        for (let i = 0; i < lines.length; i++) {
            const line = lines[i].trim();
            const lineNumber = i + 1;
            
            // 处理多行值
            if (inMultilineValue) {
                if (line.endsWith(currentVariable.quote)) {
                    // 多行值结束
                    multilineBuffer.push(line.slice(0, -1));
                    const fullValue = multilineBuffer.join('\n');
                    this.exports[currentVariable.name] = fullValue;
                    currentVariable.value = fullValue;
                    inMultilineValue = false;
                    multilineBuffer = [];
                } else {
                    multilineBuffer.push(line);
                }
                continue;
            }

            // 处理导出变量
            if (line.startsWith('export')) {
                // 修改正则表达式,只匹配引号外的注释
                const match = line.match(/^export\s+([A-Za-z0-9_]+)=(['"])((?:(?!\2).)*)\2(?:\s*#(.*))?$/);
                if (match) {
                    const [_, name, quote, value, comment] = match;
                    console.log(`发现导出变量: ${name} = ${quote}${value}${quote}`);
                    
                    // 创建变量对象
                    currentVariable = {
                        name,
                        value,
                        type: 'export',
                        lineNumber,
                        section: currentSection,
                        comment: comment ? {  // 只有引号外的#才作为注释
                            content: comment.trim(),
                            lineNumber,
                            section: currentSection
                        } : lastComment,
                        quote
                    };

                    // 添加到exports
                    this.exports[name] = value;
                    currentSection.variables.push(currentVariable);
                    continue;
                } else {
                    // 如果没有匹配到完整的引号对,尝试处理多行值
                    const basicMatch = line.match(/^export\s+([A-Za-z0-9_]+)=(['"])(.*?)$/);
                    if (basicMatch) {
                        const [_, name, quote, value] = basicMatch;
                        console.log(`发现多行变量: ${name}`);
                        
                        // 创建变量对象
                        currentVariable = {
                            name,
                            type: 'export',
                            lineNumber,
                            section: currentSection,
                            comment: lastComment,
                            quote
                        };

                        // 开始多行值收集
                        inMultilineValue = true;
                        multilineBuffer = [value];
                        this.exports[name] = '';  // 初始化为空字符串
                        currentSection.variables.push(currentVariable);
                        continue;
                    }
                }
            }

            // 处理section标题
            if (line.startsWith('##')) {
                const level = line.match(/^#+/)[0].length;
                const sectionName = line.substring(level).trim();
                
                // 创建新section
                currentSection = {
                    name: sectionName,
                    level,
                    lineNumber,
                    variables: [],
                    comments: []
                };
                this.sections.push(currentSection);
                currentSectionContent = '';  // 重置section内容
                continue;
            }

            // 收集section内容
            if (currentSection) {
                currentSectionContent += line + '\n';
            }
        }
        
        return this;
    }

    // 解析值(处理引号)
    parseValue(value) {
        console.log('解析值:', value);  // 调试输出
        
        // 去除引号
        if ((value.startsWith("'") && value.endsWith("'")) ||
            (value.startsWith('"') && value.endsWith('"'))) {
            value = value.slice(1, -1);
            console.log('去除引号后:', value);  // 调试输出
        }
        
        return value;
    }

    // 获取变量信息
    getValue(name) {
        // 查找变量
        let value = this.exports[name] || this.variables[name] || '';  // 默认返回空字符串而不是undefined
        let type = name in this.exports ? 'export' : 
                   name in this.variables ? 'variable' : null;
        
        // 查找变量所在的section
        let section = this.sections.find(s => 
            s.variables.some(v => v.name === name)
        ) || this.sections[0];
        
        // 查找变量对象
        let variable = section.variables.find(v => v.name === name);
        
        return {
            name,
            value,  // 现在总是返回字符串
            type,
            section: {
                name: section?.name || '',
                level: section?.level || 0,
                lineNumber: section?.lineNumber || 0,
                commentCount: section?.comments?.length || 0,
                variableCount: section?.variables?.length || 0
            },
            comments: variable?.comment ? [{
                content: variable.comment.content,
                lineNumber: variable.comment.lineNumber
            }] : []
        };
    }

    // 设置变量值
    setValue(name, value, options = {}) {
        const isExport = options.isExport !== undefined ? options.isExport : (name in this.exports);
        const varInfo = this.getValue(name);

        // 更新或添加变量
        if (isExport) {
            this.exports[name] = value;
            delete this.variables[name];
        } else {
            this.variables[name] = value;
            delete this.exports[name];
        }

        // 如果是新变量,添加到指定section
        let targetSection;

        if (options.section) {
            targetSection = this.sections.find(s => s.name === options.section);
        } else if (varInfo.section && varInfo.section.name) {
            targetSection = this.sections.find(s => s.name === varInfo.section.name);
        } else {
            targetSection = this.sections[0];
        }

        if (!targetSection) {
            targetSection = this.sections[0];
        }

        // 检查变量是否已存在于section中
        const existingVarIndex = targetSection.variables.findIndex(v => v.name === name);

        if (existingVarIndex >= 0) {
            // 更新现有变量
            targetSection.variables[existingVarIndex].value = value;
            targetSection.variables[existingVarIndex].type = isExport ? 'export' : 'variable';
        } else {
            // 添加新变量
            targetSection.variables.push({
                name,
                value,
                type: isExport ? 'export' : 'variable',
                lineNumber: 999999, // 放在section的最后
                section: targetSection
            });
        }

        return this.getValue(name);
    }

    // 转换为字符串
    toString() {
        const lines = [];
        
        for (const section of this.sections) {
            if (section.lineNumber > 0) {
                lines.push('');
            }
            
            // 添加section标题
            if (section.level > 1) {
                lines.push(`${'#'.repeat(section.level)} ${section.name}`);
            }
            
            // 添加变量
            section.variables.forEach(variable => {
                if (variable.name in this.exports) {
                    const value = this.exports[variable.name];
                    const quote = variable.quote || "'";  // 默认使用单引号
                    let line = `export ${variable.name}=${quote}${value}${quote}`;
                    
                    // 如果有行尾注释,添加它
                    if (variable.comment && variable.comment.content) {
                        line += ` #${variable.comment.content}`;
                    }
                    
                    lines.push(line);
                }
            });
        }
        
        return lines.join('\n');
    }

    // 保存到文件
    saveToFile(filePath) {
        try {
            const content = this.toString();
            fs.writeFileSync(filePath, content, 'utf-8');
            return true;
        } catch (error) {
            console.error('保存文件失败:', error);
            return false;
        }
    }
}
// 解析shell文件
function parseShellFile(input, options = {}) {
    const parser = new ShellParser();
    
    if (options.isContent) {
        return parser.parseFile(input);
    } else {
        try {
            const content = fs.readFileSync(input, 'utf-8');
            return parser.parseFile(content);
        } catch (error) {
            console.warn('无法读取文件,尝试直接解析内容');
            return parser.parseFile(input);
        }
    }
}

0

评论区