作为对 Tanaike 的补充,此答案旨在说明如果您必须使用 findText() 方法(例如同时更改元素属性、突出显示匹配范围等)可以做什么。
问题是“数据”现在是整个段落
嗯,这正是由于提供的说明:
-
getElement() 的结果是Element 本身。
-
asText() 在Element 上的结果是Text 实例。
-
getText() 在Text 上的结果是,引用文档:
元素的内容作为文本字符串
有没有办法捕获和使用数据
在撰写本文时,findText() 似乎不可能按照 docs 引用,以供后代参考:
不完全支持 JavaScript 正则表达式功能的子集,例如捕获组和模式修饰符。
怎么办?
找到匹配项后,findText() 会返回一个 RangeElement 实例,该实例有两个感兴趣的方法:getStartOffset() 和 getEndOffsetInclusive()。这些方法的返回值指向元素文本内容的字符索引。因此,可以通过substring()方法(或slice())提取匹配的子字符串。
您可以使用findText()方法的from参数递归迭代匹配结果以获得所有匹配范围。
/**
* @summary pattern wrapper
* @param {string} linkPattern
* @param {RegExp} [infoPattern]
*/
const matchText = (linkPattern, infoPattern) =>
/**
* @summary finds links in text elements
* @param {GoogleAppsScript.Document.Paragraph} elem
* @param {string} [text]
* @param {GoogleAppsScript.Document.RangeElement} [from]
* @param {string[]} [matches]
* @returns {string[][]}
*/
(elem, text = elem.getText(), from, matches = []) => {
const match = from ?
elem.findText(linkPattern, from) :
elem.findText(linkPattern);
if(match) {
const rangeStart = match.getStartOffset();
const rangeEnd = match.getEndOffsetInclusive();
const link = text.substring( rangeStart, rangeEnd + 1 );
const [ full, ...groups ] = link.match( infoPattern );
matches.push(groups);
return matchText(linkPattern, infoPattern)(elem, text, match, matches);
}
return matches;
}
用于测试的驱动脚本:
function findText() {
const doc = getTestDoc(); //gets doc somehow, not provided here
const body = doc.getBody();
const par = body.appendParagraph("Some paragraph with some data in it https://example.com/ford/some/other/data.html.\nThere is another link also here https://example.com/ford/latest.html.");
const pattern = 'http(?:s)*:\/\/(?:www\.)*example\.com\/\\w+';
const targetPattern = /\/(\w+)$/;
const results = matchText(pattern,targetPattern)(par);
Logger.log(results); //[[ford], [ford]]
}
备注
- 好奇的观察:显然,要将标记(
\w、\s 等)传递给表达式 string,必须转义反斜杠(例如 \\w 将被解析正确)。
- 请注意,上面的解决方案返回一个
string[][] 以提取所有捕获组()
- 上面的示例代码是为 V8 运行时设计的。
参考文献
-
getElement()spec
-
asText()spec
-
getText()spec
-
findText()spec
-
getStartOffset()spec
-
getEndOffsetInclusive()spec
-
substring() docs 在 MDN 上