问题描述
今天我在这里得到了极大的帮助!
我正在尝试做其他事情。我在Google文档中有一个编号为问题的列表,我想用其他内容代替这些数字。
例如,我想替换列表中的数字,例如:
-
地球在一年中的哪个月最接近太阳? 〜七月 〜六月 =一月 〜三月 〜9月
-
在澳大利亚(南半球),白天什么时候最短而夜晚什么时候最长? 〜十二月底 〜三月下旬 =六月底 〜四月下旬 在澳大利亚,一年四季的白天和黑夜的长度几乎相同
使用:
:: 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;
}
}