Apps Script函数源码换行符异常显示问题求助
问题描述
我编写了以下代码,希望无需操作页面完整源码即可直接访问函数。数据最初来自Apps Script API,目前从文件中提取:
function readingAJSONFile() { const ss = SpreadsheetApp.getActive(); const sh = ss.getSheetByName("Sheet0"); const file = DriveApp.getFileById(gobj.globals.SOFJSONId); var jOb = JSON.parse(file.getBlob().getDataAsString()); let files = jOb.files; if (files && files.length > 0) { var cOb = files.reduce((a, f, i) => { //Logger.log(f.name); a.table.push([f.name, f.type, "", ""]); if (f.type == "SERVER_JS" && f.source != null) { a.source = JSON.stringify(f.source);//The is where I stringified the file source code //Logger.log('a.source: %s',a.source); } if (f.functionSet) { if (f.functionSet.values) { f.functionSet.values.forEach(obj => { let re = new RegExp(`function\s+${obj.name}\([^)]*\)\s*\{.*?\\n\}\\n`, "g"); if (a.source.match(re)) { let src = a.source.match(re)[0];//once I began to stringy from above then this start functioning a.table.push(["", "", obj.name, src]) } }); } }; return a; }, { source: "", table: [["FileName", "FileType", "Functions", "Source"]] }); } if (cOb.table && cOb.table.length > 0) { return cOb.table; } } function startADialog(){ SpreadsheetApp.getUi().showModelessDialog(HtmlService.createTemplateFromFile('ah1').evaluate().setWidth(1000).setHeight(500),"My Data"); }
我通过getDataAsString()打开文件并使用JSON.parse解析,这一步正常。但使用正则表达式从文件源码中提取函数源码后,提取出的源码换行符显示为转义字符而非正常渲染,且该功能目前无法稳定运行。我不理解如何修复此问题,数据最初来自Apps Script API,我将其序列化后保存到文件中以便处理。
此外,数据来源与以下请求获取的内容一致:
const scriptId = gobj.globals.scriptid; const url = "https://script.googleapis.com/v1/projects/" + scriptId + "/content?fields=files(functionSet%2Cname%2Ctype)"; const options = { "method": "get", "headers": { "Authorization": "Bearer " + ScriptApp.getOAuthToken() } }; const res = UrlFetchApp.fetch(url, options); let data = JSON.parse(res.getContentText()); let files = data.files.filter(f => f.type == "SERVER_JS");
解决方案
1. 修复换行符转义问题
你对源码执行JSON.stringify(f.source)会把原始换行符转成\n转义形式,这是问题根源。直接使用原始源码字符串即可,无需序列化:
// 原代码 a.source = JSON.stringify(f.source); // 修改为 a.source = f.source;
同时调整正则表达式,去掉双重转义的换行符,改用[\s\S]匹配所有字符(包括换行),避免截断函数体:
// 原正则 let re = new RegExp(`function\s+${obj.name}\([^)]*\)\s*\{.*?\\n\}\\n`, "g"); // 修改为 let re = new RegExp(`function\\s+${obj.name}\\([^)]*\\)\\s*\\{[\\s\\S]*?\\n\\}`, "g");
2. 提升正则匹配稳定性
原正则无法处理函数内部嵌套大括号的情况,且依赖末尾换行符容易失效,优化后的匹配逻辑如下:
f.functionSet.values.forEach(obj => { // 支持简单嵌套大括号的函数匹配 const funcRegex = new RegExp( `function\\s+${obj.name}\\([^)]*\\)\\s*\\{([\\s\\S]*?)\\}`, "g" ); const matches = a.source.match(funcRegex); if (matches) { let src = matches[0]; // 清理残留转义字符(若有) src = src.replace(/\\n/g, "\n"); a.table.push(["", "", obj.name, src]); } });
如果需要处理复杂嵌套大括号,需添加大括号计数器逻辑跟踪层级,避免提前匹配到闭合括号。
3. 确保数据读写一致性
保存API数据到Drive文件时,直接序列化整个响应对象即可,不要单独处理源码字段:
// 保存API数据示例 const file = DriveApp.createFile("script-data.json", JSON.stringify(data), "application/json");
这样读取后jOb.files[x].source就是原始源码字符串,不会产生额外转义。
内容的提问来源于stack exchange,提问作者Cooper
相关产品推荐
相关产品推荐

