【发布时间】:2019-11-10 21:52:29
【问题描述】:
我需要使用 VBA 对数学表达式进行标记。我有一个可行的解决方案,但正在寻找一种更有效的方法(可能是 RegExp)。
我目前的解决方案:
Function TokeniseTheString(str As String) As String()
Dim Operators() As String
' Array of Operators:
Operators = Split("+,-,/,*,^,<=,>=,<,>,=", ",")
' add special characters around all "(", ")" and ","
str = Replace(str, "(", Chr(1) & "(" & Chr(1))
str = Replace(str, ")", Chr(1) & ")" & Chr(1))
str = Replace(str, ",", Chr(1) & "," & Chr(1))
Dim i As Long
' add special characters around all operators
For i = LBound(Operators) To UBound(Operators)
str = Replace(str, Operators(i), Chr(1) & Operators(i) & Chr(1))
Next i
' for <= and >=, there will now be two special characters between them instead of being one token
' to change < = back to <=, for example
For i = LBound(Operators) To UBound(Operators)
If Len(Operators(i)) = 2 Then
str = Replace(str, Left(Operators(i), 1) & Chr(1) & Chr(1) & Right(Operators(i), 1), Operators(i))
End If
Next i
' if there was a "(", ")", "," or operator next to each other, there will be two special characters next to each other
Do While InStr(str, Chr(1) & Chr(1)) > 0
str = Replace(str, Chr(1) & Chr(1), Chr(1))
Loop
' Remove special character at the end of the string:
If Right(str, 1) = Chr(1) Then str = Left(str, Len(str) - 1)
TokeniseTheString = Split(str, Chr(1))
End Function
使用此字符串进行测试 IF(TestValue>=0,TestValue,-TestValue) 为我提供了所需的解决方案。
Sub test()
Dim TokenArray() As String
TokenArray = TokeniseTheString("IF(TestValue>=0,TestValue,-TestValue)")
End Sub
我以前从未见过正则表达式,并尝试在 VBA 中实现this。我遇到的问题是 VBA 中的 RegExp 对象不允许 positive lookbehind。
我会欣赏比我上面的任何更有效的解决方案。
【问题讨论】:
-
作为没有 RegEx 的第一个简单步骤,您可以将第二个循环匹配 ">=" 和 "For i = 5 To 6
str = Replace(str, Left(Operators(i), 1) & Chr(1) & Chr(1) & Right(Operators(i), 1), Operators(i))Next i而无需将长度检查为基于 0 的索引5 和 6 的长度为 2。RegEx 可以很快,但无论如何都不会;您也可以考虑以二进制模式检查字符串。进一步的想法:您可以使用 XMLDom 构建令牌和运算符的层次结构 :-) ` -
RegEx将简化代码,但将字符串转换为缓冲区Dim buffer() As Byte: buffer = str并使用Select Case循环每个字符会更便宜。如果您想尝试RegEx,请使用模式"(""(?:""""|[^""])*""|[^ ()+-/\*^<>=,]+|<=|>=|\S)\s*"并替换/拆分匹配项:tokens = Split(re.Replace(str, "$1" & ChrW(-1)), ChrW(-1))。 -
你为什么认为你需要一个积极的回顾?你用了什么表达方式?
-
谢谢@FlorentB。我在下面发布了与我原来的解决方案相同的功能。你介意解释一下模式的不同部分吗?
标签: regex excel vba tokenize mathematical-expressions