如何用包含数字的标识符替换编号列表元素

How to replace numbered list elements with an identifier containing the number

今天我在这里得到了惊人的帮助!

我正在尝试做其他事情。我在 Google 文档中有一个问题编号列表,我想用其他内容替换这些数字。

例如,我想替换列表中的数字,例如:

  1. 地球在一年中的哪个月份离太阳最近? ~七月 ~六月 =一月 ~三月 ~9 月

  2. 在南半球的澳大利亚,什么时候白天最短,什么时候黑夜最长? ~12月下旬 ~三月下旬 =六月底 ~四月下旬 ~澳大利亚全年的昼夜长度几乎相同

有:

::Q09::地球在一年中的哪个月份离太阳最近? ~七月 ~六月 =一月 ~三月 ~9 月

::Q11:: 在澳大利亚(南半球)什么时候白天最短黑夜最长? ~12月下旬 ~三月下旬 =六月底 ~四月下旬 ~澳大利亚全年的昼夜长度几乎相同

我试过使用以前帖子中的建议,但只提出了以下内容,但似乎不起作用。

感谢您的光临!!!

function questionName2(){
  var body = DocumentApp.getActiveDocument().getBody();
  var text = body.editAsText();
    var pattern = "^[1-9]";
    var found = body.findText(pattern);
    var matchPosition = found.getStartOffset();
  
  while(found){
    text.insertText(matchPosition,'::Q0');
    found = body.findText(pattern, found);
  }
}

正则表达式

Text.findText(searchPattern) uses a string that will be parsed as a regular expression using Google's RE2 librarysearchPattern。以这种方式使用字符串需要我们在删除字符的特殊含义时添加额外的反斜杠,例如匹配问题编号后的句点,或使用字符匹配集,如 \d 用于数字。

^\s*\d+?\. 将匹配一组任意 non-zero 长度的数字,以任意长度(包括零)的前导白色 space 开始一行。 \d 是数字,+ 是一个或多个,组合 +? 使匹配变得懒惰。懒惰的部分这里不是必须的,但是为了避免bug,我习惯默认懒惰。另一种方法是 \d{1,2} 专门匹配 1 到 2 位数字。

要从匹配的文本中提取数字,我们可以使用 JavaScript RegExp 对象。与 Doc 正则表达式不同,此正则表达式不需要额外的反斜杠,并且允许我们使用带括号的捕获组。

^\s*(\d+?)\. 与上面几乎相同,除了没有多余的斜杠,我们现在将“保存”数字,以便我们可以在替换字符串中使用它们。我们用括号标记我们想要保存的内容。因为这将是一个普通的 JavaScript 正则表达式字面值,所以我们将整个内容用斜线括起来:/^\s*(\d+?)\./,但是开始和结束 / 只是为了表明这是一个 RegExp 字面值。

文本元素和文本字符串

Text.findText 可以 return 不仅仅是我们要求的精确匹配:它 return 是包含正则表达式匹配项的文本加上索引的整个元素。为了使用捕获组执行搜索和替换,我们必须使用索引删除旧文本,然后插入新文本。

以下赋值为我们提供了进行搜索和替换所需的所有数据:首先是元素,然后是开始和停止索引,最后使用 slice (注意 slice 使用 exclusive 结尾,而 Doc API 使用 inclusive 结尾,因此 +1).

var found = DocumentApp.getActiveDocument().getBody().findText(pattern);
var matchStart = found.getStartOffset();
var matchEnd = found.getEndOffsetInclusive();
var matchElement = found.getElement().asText();
var matchText = matchElement.getText().slice(matchStart, matchEnd + 1);

注意事项

正如 Tanaike 在评论中指出的那样,这假设编号不是 List Items,它会自动生成数字,而是您手动输入的数字。如果您使用的是自动生成的编号列表,API 不允许您编辑编号格式。

此答案还假设在示例中,当您映射“9”时。到“::Q09::”和“10”。到“::Q11::”,10 到 11 的映射是一个拼写错误。如果这是有意为之,请更新问题以阐明编号可能更改的原因。

还假设数字应该小于 100,给定“Q09”的零填充示例。该示例应该足够灵活,允许您在需要时将其更新为不同的填充方案。

完整示例

由于该问题没有使用任何 V8 功能,因此假设是较旧的 Rhino 环境。

/**
 * Replaces "1." with "::Q01::"
 */
function updateQuestionNumbering(){
  var text = DocumentApp.getActiveDocument().getBody();
  var pattern = "^\s*\d+?\.";
  var found = text.findText(pattern);
  while(found){
    var matchStart = found.getStartOffset();
    var matchEnd = found.getEndOffsetInclusive();
    var matchElement = found.getElement().asText();
    var matchText = matchElement.getText().slice(matchStart, matchEnd + 1);
    matchElement.deleteText(matchStart, matchEnd);
    matchElement.insertText(matchStart, matchText.replace(/^\s*(\d+?)\./, replacer));  
    found = text.findText(pattern, found);
  }
  
  /**
   * @param {string} _ - full match (ignored)
   * @param {string} number - the sequence of digits matched
   */
  function replacer(_, number) {
    return "::Q" + padStart(number, 2, "0") + "::";
  }
  
  // use String.prototype.padStart() in V8 environment
  // above usage would become `number.padStart(2, "0")`
  function padStart(string, targetLength, padString) {
    while (string.length < targetLength) string = padString + string;
    return string;
  }
}