Google 带有正则表达式的工作表自定义函数在范围内使用时在交替行上失败

Google sheets custom function w/ regex fails on alternating rows when used in range

我刚刚编写了一个简单的 google 表单函数来修复一些 URL。当手动传递值数组时,此函数在浏览器中运行良好。当从 google 个工作表调用时,该函数对 每隔一行 失败。

这不是数据问题,因为我可以通过将公式向下移动一行或为每个单元格单独调用它来使其适用于 "failing" 行。我认为这可能是 google 表中 regex 的问题。

var pattern = /^http:\/\/(.*\/\d\/.*)_(.*)\/(g\d+p.*)$/ig;

function encode(input) {
  if (!input) return "";
  if (input.map) {
    return input.map(encode);
  } else {
    try {
      // same error happens, at this location, w/ or w/o toString()
      var matches = pattern.exec(input.toString());
      return matches[1] + encodeURIComponent(matches[2]) + matches[3];
    } catch (e) {
      return "error=" + e.message + " value = [" + input + "] ";
    }
  }
}

编辑:为了让后来的人更清楚,当正则表达式在 "else" 子句中时,这也会以同样的方式失败:

else { 
     var matches = /^(http:\/\/.*\/\d\/.*_)(.*)(\/g\d+p.*)$/ig.exec(input.toString());
     ... continues as normal

对于数据的交替行,我收到此错误消息:

error=Cannot read property "1" from null.  value =  [ http://... ]

我试过:

在失败的情况下,我有这样的数据:

将公式移动到单元格 "B2" 并说 =encode(A2:A8) 会导致所有 "failing" 行计算而其他行失败!

详细说明我的评论,错误意味着 matches 为空或不存在,这可能意味着正则表达式未找到匹配项。所以重要的是看input的值是否应该匹配或者确实不符合正则表达式的要求

正则表达式执行以下操作:

^http:\/\/(.*\/\d\/.*)_(.*)\/(g\d+p.*)$

Debuggex Demo,匹配文本:

http://whatever/3/some_thing/g4p/can be anything
^^^^^^^        ^^^    ^     ^^^^

因此,如果在 URL 中未找到以下任何一项,则不会返回任何匹配项:

  • URL 不以 http:// 开头(但是,例如 https:// )
  • 没有出现:/,一个数字,/
  • 没有_
  • 没有出现/g,一些数字,p

您确定文本每次都满足所有这些要求吗?

简短的回答(如您对 OP 的评论所证实)是从正则表达式中删除最后的 "g"(全局标志)。


https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec

Syntax regexObj.exec(str)

Parameters str The string against which to match the regular expression.

...

If your regular expression uses the "g" flag, you can use the exec() method multiple times to find successive matches in the same string. When you do so, the search starts at the substring of str specified by the regular expression's lastIndex property (test() will also advance the lastIndex property).

因此,当您打算继续搜索同一字符串中的匹配项时,您似乎真的应该只包含全局标志。

至于为什么它在其他环境中有效,我不确定。确实,从您停止的地方继续搜索似乎有点奇怪,即使您正在将 exec 应用到一个全新的字符串 。也许 GAS 中的实现有点 "off" - 有更多知识的人可能会对此发表评论。