如何用包含数字的标识符替换编号的列表元素 正则表达式文本元素和文本字符串注意事项完整示例

问题描述

今天我在这里得到了极大的帮助!

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

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

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

  2. 在澳大利亚(南半球),白天什么时候最短而夜晚什么时候最长? 〜十二月底 〜三月下旬 =六月底 〜四月下旬 在澳大利亚,一年四季的白天和黑夜的长度几乎相同

使用:

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

:: Q11 ::在澳大利亚(南半球),白天什么时候最短而夜晚什么时候最长? 〜十二月底 〜三月下旬 =六月底 〜四月下旬 在澳大利亚,一年四季的白天和黑夜的长度几乎相同

我尝试使用以前的帖子中的建议,但是只提出了以下内容,这似乎行不通。

谢谢你在这里

filterData()

解决方法

正则表达式

Text.findText(searchPattern)使用一个字符串,该字符串将被Google regular expression用作searchPattern解析为RE2 library。以这种方式使用字符串时,无论何时要从字符中删除特殊含义(例如,匹配问题编号后的句点或将数字\d用作字符匹配集)时,都需要添加一个额外的反斜杠。

^\\s*\\d+?\\.将匹配一组以非零长度开头的一行数字,该数字以任意长度(包括零)开头的空格。 \d是数字,+是一个或多个,并且组合+?使匹配变得懒惰。此处不需要惰性部分,但是我的习惯是默认为惰性以避免错误。可以选择\d{1,2}来专门匹配1到2位数字。

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

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

文本元素和文本字符串

Text.findText不仅可以返回我们要求的完全匹配:还可以返回包含文本以及正则表达式匹配内容的索引的整个元素。为了执行搜索并用捕获组替换,我们必须使用索引来删除旧文本,然后插入新文本。

以下分配为我们提供了执行搜索和替换所需的所有数据:首先是元素,然后是开始和停止索引,最后使用slice提取匹配的文本字符串(请注意, slice使用专用末尾,而Doc API使用专用末尾,即+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的映射是一个错字。如果这样做是故意的,请更新问题以阐明为什么编号可能会更改的规则。

还假定假设“ Q09”的零填充示例中的数字小于100。该示例应足够灵活,以便您可以根据需要将其更新为其他填充方案。

完整示例

由于该问题未使用任何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;
  }
}