正则表达式执行时间限制如何在Google Apps脚本中工作? TLDR:完整帖子: MCVE:部分答案:

问题描述

TLDR:

这个任意RegExp执行时间限制是多少?它有多长时间?何时应用(因为它并非在所有Google Apps脚本上下文中均适用)?另外,当整个脚本已经有执行时间限制时,为什么还要应用它?

完整帖子:

我突然遇到了错误

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

在Google Apps脚本中。在我创建的Google表格上使用自定义菜单运行功能时遇到此错误。这样便形成了一个简短的UI,要求用户输入电子表格网址,然后使用提供的网址(和电子表格)运行功能

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

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

这使我相信对正则表达式有一个任意的时间限制,该时间限制要么是因为已从自定义菜单调用了该函数,要么该函数短暂地使用了UI,要么该函数调用一个库(或某些这些的组合。)

这个任意RegExp执行时间限制是多少?它有多长时间?何时应用(因为它并非在所有Google Apps脚本上下文中均适用)?另外,当整个脚本已经有执行时间限制时,为什么还要应用它?

在Google Apps脚本的Google文档中,我找不到任何提及此特定错误/时间限制/配额的信息。

为清楚起见,我检查了他们使用的UI脚本是否使用了正确的库版本(并且开发模式始终处于启用状态,因此它使用的是最新版本)。我还确认通过控制台打印,相同的函数使用相同的变量运行,所以我知道唯一的区别是该函数调用方式。

这是RegExp,它在一个上下文中打破了时间限制,但在其他情况下则没有,如果出于某种原因需要时,则打破了该限制:

/[\s\<\>]*\d+\s*(?:(?:l\s*f|linear\s*feet|lin\s*feet|lin\s*ft)|(?:s\s*f|square\s*feet|sq\s*\ft|sq\s*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相邻的储藏室和机械室6 15 EA ACPFI RMV 注意:天花板中间,5个损坏的配件。 RMV全部。 0 SF防火,外壳,天花板上方 见注

要重现失败的上下文,请在Google表格中使用脚本编辑器(作为文档绑定脚本)创建自定义菜单,然后单击“测试”按钮。

容器绑定脚本代码

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*(?:(?:l\s*f|linear\s*feet|lin\s*feet|lin\s*ft)|(?:s\s*f|square\s*feet|sq\s*\ft|sq\s*feet|sq)|(?:ea|each))(?:[\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()时,也会失败。

要重现成功的执行上下文,请创建一个独立的Google Apps脚本(而不是从电子表格中创建),然后在脚本编辑器中运行testFun()

独立脚本代码

function testFun() {
  var regExp = /[\s\<\>]*\d+\s*(?:(?:l\s*f|linear\s*feet|lin\s*feet|lin\s*ft)|(?:s\s*f|square\s*feet|sq\s*\ft|sq\s*feet|sq)|(?:ea|each))(?:[\s\,Above ceiling tiles <Category: 3> See note';
  text.match(regExp);
  Logger.log('This line will be successfully reached');
}

解决方法

部分答案:

  • 该问题在引擎中可重现。
  • 该问题似乎在引擎中无法再现

这似乎解释了执行上下文的差异。鉴于引擎已弃用,您不太可能找到问题的确切限制或原因(但似乎是300毫秒左右)。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...