如何自动提取含'return N('的JS函数并移除原代码中对应函数?
问题描述
我有一段包含大量函数的JavaScript代码,其中部分函数含有代码return N(。我想要一种自动方法,收集所有包含return N(的完整函数,将其复制到另一个JavaScript文件中,然后从原代码中删除这些函数。由于代码量很大,如何快速自动完成这个操作?
示例代码:
function mr(J,m){return N(m- -0x3d8,J);} function mi(J,m){return N(m- -0x192,J);} function mL(J,m){return N(J-0x2bc,m);}
我尝试了以下代码,但效果不佳:
// Define a regular expression to match functions that contain the code 'return N(' const regex = /function\s*\w*\s*\([^)]*\)\s*{[\s\S]*?return N\(/g; // Define the original code as a string const originalCode = ` function foo() { // do something return N(value); } function bar() { // do something else return N(value); } function baz() { // do something else return otherValue; } `; // Use the regular expression to match all functions that contain the code 'return N(' const matches = originalCode.match(regex); // If any matches were found if (matches) { // Create an empty array to store the modified functions const modifiedFunctions = []; // Loop through the matches for (const match of matches) { // Use string manipulation techniques to remove the function from the original code const modifiedFunction = match.replace(/function\s*\w*\s*\([^)]*\)\s*{/, '').replace(/}$/, ''); // Add the modified function to the array modifiedFunctions.push(modifiedFunction); } // Join the modified functions into a single string const modifiedCode = modifiedFunctions.join('\n'); // Log the modified code console.log(modifiedCode); }
解决方案
方法一:改进正则表达式(适合简单场景)
你之前的正则仅匹配到return N(的位置,未覆盖完整函数体。可以使用支持平衡括号的正则来匹配完整函数:
const fs = require('fs'); // 读取原文件内容 const originalCode = fs.readFileSync('./original.js', 'utf8'); // 匹配包含return N(的完整函数,支持平衡大括号 const funcRegex = /function\s+(\w+)\s*\([^)]*\)\s*\{(?:[^{}]+|\{(?:[^{}]+|\{[^{}]*\})*\})*return N\([^)]*\);?(?:[^{}]+|\{(?:[^{}]+|\{[^{}]*\})*\})*\}/g; const matchedFuncs = []; let match; // 收集所有符合条件的函数 while ((match = funcRegex.exec(originalCode)) !== null) { matchedFuncs.push(match[0]); } // 生成移除目标函数后的原代码,清理多余空行 const modifiedOriginal = originalCode.replace(funcRegex, '').replace(/^\s*\n/gm, ''); // 将收集到的函数写入新文件 fs.writeFileSync('./extracted-funcs.js', matchedFuncs.join('\n\n')); // 将处理后的代码写回原文件(操作前务必备份原文件) fs.writeFileSync('./original.js', modifiedOriginal);
说明:这种方式在函数体嵌套复杂大括号时可能失效,适合示例中这种简单函数或嵌套较浅的场景。
方法二:AST解析(可靠处理复杂代码)
对于大规模、结构复杂的JavaScript代码,正则容易出错,建议使用AST(抽象语法树)工具解析,比如@babel系列工具:
步骤1:安装依赖
npm install @babel/parser @babel/traverse @babel/generator
步骤2:编写处理脚本
const fs = require('fs'); const parser = require('@babel/parser'); const traverse = require('@babel/traverse').default; const generate = require('@babel/generator').default; // 读取原文件代码 const code = fs.readFileSync('./original.js', 'utf8'); // 解析代码生成AST const ast = parser.parse(code, { sourceType: 'script' }); const extractedFuncs = []; const nodesToRemove = []; // 遍历AST,筛选包含return N(的函数 traverse(ast, { FunctionDeclaration(path) { let hasReturnN = false; // 遍历函数体内的return语句 path.traverse({ ReturnStatement(returnPath) { const callExpr = returnPath.node.argument; // 判断是否是调用N()的return语句 if (callExpr?.type === 'CallExpression' && callExpr.callee.name === 'N') { hasReturnN = true; returnPath.stop(); // 找到后停止遍历当前函数 } } }); if (hasReturnN) { extractedFuncs.push(generate(path.node).code); nodesToRemove.push(path); } } }); // 移除标记的函数节点 nodesToRemove.forEach(path => path.remove()); // 生成处理后的代码 const modifiedCode = generate(ast).code; // 写入文件 fs.writeFileSync('./extracted-funcs.js', extractedFuncs.join('\n\n')); fs.writeFileSync('./original.js', modifiedCode);
说明:AST解析能准确处理各种复杂场景,比如嵌套函数、多行函数体、注释等,是处理大规模JS代码的最优方案。
注意事项
- 操作前必须备份原代码文件,防止数据丢失。
- 先在小样本代码上验证脚本效果,再应用到大规模代码。
内容的提问来源于stack exchange,提问作者Jemey Gaming
相关产品推荐
相关产品推荐

