正则表达式执行时间限制如何在Google Apps脚本中工作



TLDR:

这个任意的RegExp执行时间限制是什么,它有多长,什么时候适用(因为它在所有谷歌应用程序脚本上下文中并不平等适用(?此外,当整个脚本已经有执行时间限制时,为什么它适用?

完整帖子:

我突然碰到错误

"错误:正则表达式操作超出了执行时间限制">

在谷歌应用程序脚本中。我在使用我创建的谷歌工作表上的自定义菜单运行函数时遇到了这个错误。这会生成一个简短的UI,请求用户输入电子表格url,然后使用提供的url(和电子表格(运行一个函数。

我以前运行过这个函数,它运行得很好,但现在我遇到了这个正则表达式时限错误。需要明确的是,这个脚本远远没有达到脚本执行的最大时间限制,只是很明显我的正则表达式太长了。我已经确定正则表达式的行(它重复运行,通常很好,并且一直工作到现在(没有明显的缺陷。它是一个大型正则表达式,但文本不是很长。它在217个字符的文本上失败。

此外,我发现当我从谷歌应用程序脚本编辑器运行等效函数时(没有UI,它只是从我创建的谷歌应用程序库中调用相同的函数(,不会发生错误。需要明确的是,我确信工作执行中的变量和环境是相同的。它在8秒内完成,解析了相同的文本,并使用了相同的正则表达式。

这让我相信,有一个适用于正则表达式的任意时间限制,这要么是因为函数是从自定义菜单调用的,要么是函数短暂使用UI,要么是该函数调用库(或它们的某种组合(。

这个任意的RegExp执行时间限制是什么,它有多长,什么时候适用(因为它在所有谷歌应用程序脚本上下文中并不平等适用(?此外,当整个脚本已经有执行时间限制时,为什么它适用?

我在谷歌的谷歌应用程序脚本文档中找不到任何提到这个特定错误/时间限制/配额的内容。

要明确的是,我已经检查了他们使用的UI脚本是否使用了正确的库版本(而且开发模式已经打开,所以它使用的是最新的版本(。我还通过控制台打印确认了相同的函数使用相同的变量运行,所以我知道唯一的区别是函数的调用方式。

如果您出于某种原因需要,以下是RegExp,它在一个上下文中打破了时间限制,但在另一个上下文则没有:

/[s<>]*d+s*(?:(?:ls*f|linears*feet|lins*feet|lins*ft)|(?:ss*f|squares*feet|sqs*ft|sqs*feet|sq)|(?:ea|each))(?:[s,]*S+){0,7}s*,s*(?:(?:(?:(?:remove|removal|(?:(?:^|s)+rem(?:s|.|:|-|$))|(?:(?:^|s)+rmv(?:s|.|:|-|$))))|(?:(?:encapsulate|encapsulation|(?:^|s)+encp?(?:ap)?(?:$|s|.|-|:)+|(?:^|s)+cap(?:$|s|.|-|:)+|(?:^|s)+enp(?:$|s|.|-|:)+|(?:^|s)+seal(?:$|s|.|-|:)+))|(?:enclose)))/gi

MCVE:

以下是一些在一个上下文中失败但在另一个上下文没有失败的文本:

第6阶段AHERA附近的仓库和机械室15EA ACPFI RMV<类别:3>注:天花板中间,5个配件损坏。RMV全部。0 SF防火,外壳,天花板上方瓷砖<类别:3>参见注释

要重现失败的上下文,请在Google Sheets电子表格中,使用脚本编辑器创建一个自定义菜单(作为文档绑定脚本(,然后单击";测试";按钮

集装箱绑定脚本代码:

function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ui = SpreadsheetApp.getUi();
ui.createMenu('Test Menu').addItem('Test', 'testFun').addToUi();
}
function testFun() {
var regExp = /[s<>]*d+s*(?:(?:ls*f|linears*feet|lins*feet|lins*ft)|(?:ss*f|squares*feet|sqs*ft|sqs*feet|sq)|(?:ea|each))(?:[s,]*S+){0,7}s*,s*(?:(?:(?:(?:remove|removal|(?:(?:^|s)+rem(?:s|.|:|-|$))|(?:(?:^|s)+rmv(?:s|.|:|-|$))))|(?:(?:encapsulate|encapsulation|(?:^|s)+encp?(?:ap)?(?:$|s|.|-|:)+|(?:^|s)+cap(?:$|s|.|-|:)+|(?:^|s)+enp(?:$|s|.|-|:)+|(?:^|s)+seal(?:$|s|.|-|:)+))|(?:enclose)))/gi;
var text = 'Storage and Mechanical Room 6 adjacent to Stage- 6 month AHERA 15 EA ACPFI RMV <Category: 3> Note: Middle of ceiling, 5 damaged fittings. RMV all. 0 SF Fireproofing, Enclosure, Above ceiling tiles <Category: 3> See note';
text.match(regExp);
Logger.log('This line will not be reached because of error');
}

在脚本编辑器中从绑定到容器的脚本运行testFun()时,它也会失败。

要重现成功的执行上下文,请创建一个独立的谷歌应用程序脚本(不是从电子表格中(,并在脚本编辑器中运行testFun()

独立脚本代码:

function testFun() {
var regExp = /[s<>]*d+s*(?:(?:ls*f|linears*feet|lins*feet|lins*ft)|(?:ss*f|squares*feet|sqs*ft|sqs*feet|sq)|(?:ea|each))(?:[s,]*S+){0,7}s*,s*(?:(?:(?:(?:remove|removal|(?:(?:^|s)+rem(?:s|.|:|-|$))|(?:(?:^|s)+rmv(?:s|.|:|-|$))))|(?:(?:encapsulate|encapsulation|(?:^|s)+encp?(?:ap)?(?:$|s|.|-|:)+|(?:^|s)+cap(?:$|s|.|-|:)+|(?:^|s)+enp(?:$|s|.|-|:)+|(?:^|s)+seal(?:$|s|.|-|:)+))|(?:enclose)))/gi;
var text = 'Storage and Mechanical Room 6 adjacent to Stage- 6 month AHERA 15 EA ACPFI RMV <Category: 3> Note: Middle of ceiling, 5 damaged fittings. RMV all. 0 SF Fireproofing, Enclosure, Above ceiling tiles <Category: 3> See note';
text.match(regExp);
Logger.log('This line will be successfully reached');
}

部分答案:

  • 该问题在rhino引擎中可重复出现
  • 这个问题在v8引擎中似乎无法重现

这似乎解释了执行上下文的差异。考虑到犀牛引擎的弃用,你不太可能找到问题的确切限制或原因(但似乎在300毫秒左右(。

相关内容

  • 没有找到相关文章

最新更新