从公式字符串中解析出Excel函数

4
我有一个包含Excel公式的字符串,如何从中解析出每个特定函数名称?
我无法想出如何编写正则表达式。基本上,它必须是括号前面的字符序列,而不在单引号或双引号内。
例如:
1. `=VLOOKUP($A9,'Summary'!$A$10:$C$30,3,FALSE)` - 应返回`VLOOKUP` 2. `=IFERROR((C10/B10),"N/A")` - 应返回`IFERROR` 3. `='New Chart Data (Date)'!L70` - 不应返回任何函数,因为没有函数 4. `=IFERROR((C10/B10),Len(E30))` - 应返回`IFERROR`和`LEN` 5. `='New Chart Data(Date)'!L70 + Len(5)` - 应返回`Len`。这是棘手的一种情况。许多都会错误地返回`Data`。
有什么想法吗?
提前感谢。

你难道不需要在做这个之前,用平衡文本的正则表达式,并且了解所有关键字、结构和变量名吗? - user557597
该字符串已知包含一个公式,因此这些额外的检查没有必要。 - Andy G
所以,没有解析公式的规则..有趣。 - user557597
2个回答

2
我想你可以像这样使用... (您可以使用类似以下内容的东西,我猜...)
(?<=[=,])[A-Za-z2]+(?=\()

正则表达式101演示(带有正则表达式的描述)

实际上,有一个小问题:像=IFERROR((C10/B10), Len(E30))这样的公式将不会得到Len。您可以使用以下公式代替,并修剪任何空格:

(?<=[=,])\s*[A-Za-z2]+(?=\()

或者因为C#接受可变长度的后顾断言......

(?<=[=,]\s*)[A-Za-z2]+(?=\()

我认为这需要比之前更多的资源。

编辑:我没有考虑到工作表名称可以采用=Sheet(2)的形式,例如='=Sheet(2)'!A1

(?<=[=,])\s*[A-Za-z2]+(?=\()(?![^']*'!)

改进的regex101

编辑2:还忘记了运算符...我想我会像Andy一样使用单词边界,因为唯一的问题是

\b[A-Za-z2]+(?=\()(?![^']*'!)

updated regex101


1
太棒了!(再来几个) - crthompson
为什么需要在表达式开头加上 (?<=[=,])? - Rafi
@Rafi 这是为了确保文本前面有等号或逗号。这将避免出现类似 Sheet(1) 的工作表名称的匹配。我还忘记了其他一些东西!在我的答案中有更详细的解释。 - Jerry
@Jerry 说得好,但它也无法匹配第5个Len。我刚刚添加了第5个。 - Rafi
@Rafi 糟糕,还有其他的操作员!我的天啊,我错过了很多。给我几分钟... - Jerry
@Rafi 我拿了我为另一个问题制作的公式,并将其添加到其他公式中,我认为这使得验证集更完整了。更新的正则表达式 - Jerry

1

我认为它可以简化,使用单词边界 \b 而不是回顾后面:

\b([A-Za-z2]+)(?=\()

你刚刚添加了那个 ;). 在这种情况下,我个人仍然会使用我的正则表达式,并在C#中创建一个集合,可能是HashSet,包含所有Excel函数名称; 大约有300个。 我会拒绝不在此列表中的匹配项。(如果有人将函数名称用作工作表名称,那么我会认真地与他们谈话!) - Andy G
或者,我可以对字符串运行两个正则表达式,一个用于剥离撇号之间的所有内容。但我猜你仍然在追求单一正则表达式的解决方案 :) - Andy G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接