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://... ]
我试过:
- 将正则表达式放入
try{}
- 将正则表达式放入
encode{}
函数中
- 编写两个单独的函数(一个用于执行 1 个值)
在失败的情况下,我有这样的数据:
- A1-A8 中有 URL
- B1 的公式为“=encode(A1:A8)”
- B1、B3、B5、B7数据完美计算
- B2、B4、B6、B8 中的数据出错(显示我的错误消息)
将公式移动到单元格 "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" - 有更多知识的人可能会对此发表评论。
我刚刚编写了一个简单的 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://... ]
我试过:
- 将正则表达式放入
try{}
- 将正则表达式放入
encode{}
函数中 - 编写两个单独的函数(一个用于执行 1 个值)
在失败的情况下,我有这样的数据:
- A1-A8 中有 URL
- B1 的公式为“=encode(A1:A8)”
- B1、B3、B5、B7数据完美计算
- B2、B4、B6、B8 中的数据出错(显示我的错误消息)
将公式移动到单元格 "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" - 有更多知识的人可能会对此发表评论。