常用表达
Text.findText(searchPattern)
使用将使用 Google 的RE2 库将其解析为正则表达式的字符串。以这种方式使用字符串需要在从字符中删除特殊含义时添加额外的反斜杠,例如匹配问题编号后的句点,或使用字符匹配集(如数字)。searchPattern
\d
^\\s*\\d+?\\.
将匹配一组数字,任何非零长度,以任何长度(包括零)的前导空白开始一行。\d
是数字,+
是一个或多个,并且组合+?
使匹配变得懒惰。这里不需要懒惰的部分,但我的习惯是默认懒惰以避免错误。另一种方法是\d{1,2}
专门匹配 1 到 2 位数字。
要从匹配的文本中提取数字,我们可以使用 JavaScript RegExp对象。与 Doc 正则表达式不同,此正则表达式不需要额外的反斜杠,并且允许我们使用带括号的捕获组。
^\s*(\d+?)\.
几乎与上面相同,除了没有多余的斜杠,我们现在将“保存”数字,以便我们可以在替换字符串中使用它们。我们用括号标记我们想要保存的内容。因为这将是一个普通的 JavaScript 正则表达式文字,所以我们将整个内容用斜杠: 包裹起来/^\s*(\d+?)\./
,但开始和结束/
只是为了表明这是一个 RegExp 文字。
文本元素和文本字符串
Text.findText
可以返回的不仅仅是我们要求的完全匹配:它返回包含文本的整个元素以及正则表达式匹配的索引。为了使用捕获组执行搜索和替换,我们必须使用索引删除旧文本,然后插入新文本。
以下分配为我们提供了进行搜索和替换所需的所有数据:首先是元素,然后是开始和停止索引,最后使用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 的映射是一个错字。如果这是有意的,请更新问题以阐明编号可能会更改的规则。
还假设数字应该小于 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;
}
}