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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:20:58