介绍
(如果你对介绍感到无聊,可以跳到假设...)
这个问题并不是特别针对VBScript(我只是在这种情况下使用它):我想找到一个通用的正则表达式用法解决方案(包括编辑器)。
这起源于我想创建一个适应MS Excel的示例4,其中3个捕获组用于将数据拆分到3个单元格中。我需要捕获一个完整的模式,然后在其中捕获另外3个模式。但是,在同一个表达式中,我还需要捕获另一种类型的模式,并再次捕获其中的3个模式(是的我知道…但在指责我之前,请先读完以下内容)。
我首先考虑了命名捕获组,然后我意识到我不应该«混合命名和编号的捕获组»,因为它«不被推荐,因为各种语言如何编号组是不一致的」。
然后我看了看VBScript SubMatches和非捕获组,我为特定情况找到了一种可行的解决方案:
For Each C In Myrange
strPattern = "(?:^([0-9]+);([0-9]+);([0-9]+)$|^.*:([0-9]+)\s.*:([0-9]+).*:([a-zA-Z0-9]+)$)"
If strPattern <> "" Then
strInput = C.Value
With regEx
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = strPattern
End With
Set rgxMatches = regEx.Execute(strInput)
For Each mtx In rgxMatches
If mtx.SubMatches(0) <> "" Then
C.Offset(0, 1) = mtx.SubMatches(0)
C.Offset(0, 2) = mtx.SubMatches(1)
C.Offset(0, 3) = mtx.SubMatches(2)
ElseIf mtx.SubMatches(3) <> "" Then
C.Offset(0, 1) = mtx.SubMatches(3)
C.Offset(0, 2) = mtx.SubMatches(4)
C.Offset(0, 3) = mtx.SubMatches(5)
Else
C.Offset(0, 1) = "(Not matched)"
End If
Next
End If
Next
124;12;3
我的 id1:213 我的 id2:232 我的 word:ins4yanrgx
:8587459 :18254182540215 :dcpt
0;1;2
它返回前两个带数字的单元以及第三个带数字或单词的单元。 基本上,我使用了一个非捕获组和两个“父”模式(“父” = 广泛的模式,用于检测其他子模式)。 如果第一个父模式有匹配的子模式(第一个捕获组),则将其值以及此模式的其余捕获组放在这三个单元格中。 如果没有,则检查是否匹配了第二个父模式的第四个捕获组,并将剩余的子模式放在相同的三个单元格中。
如果...
不是像这样:
(?:^(\d+);(\d+);(\d+)$|^.*:(\d+)\s.*:(\d+).*:(\w+)$|what(ever))
类似这样的事情是可能的:
(#:^(\d+);(\d+);(\d+)$)|(#:^.*:(\d+)\s.*:(\d+).*:(\w+)$)|(#:what(ever))
使用(#:
不是创建一个非捕获组,而是创建一个“父”编号的捕获组。
这样我就可以类似于示例4中所做的事情:
C.Offset(0, 1) = regEx.Replace(strInput, "#$1")
C.Offset(0, 2) = regEx.Replace(strInput, "#$2")
C.Offset(0, 3) = regEx.Replace(strInput, "#$3")
它会搜索父模式,直到在子模式中找到匹配项(第一个匹配项将被返回,并且理想情况下不会搜索剩余的模式)。
已经有类似的东西了吗?或者我从正则表达式中漏掉了什么可以做到这一点的东西吗?
其他可能的变化:
- 直接引用父模式和子模式,例如:
#2$3
(这相当于我的示例中的$6
); - 在其他捕获组内创建尽可能多的捕获组(我猜这将更加复杂,但也是最有趣的部分),例如:
(#:^_(?:(#:(\d+):\w+-(\d))|(#:\w+:(\d+)-(\d+)))_$)|(#:^\w+:\s+(#:(\w+);\d-(\d+))$)
和在模式中提取##$1
:_123:smt-4_
它将匹配:123
_ott:432-10_
它将匹配:432
yant: special;3-45235
它将匹配:special
请告诉我是否注意到此逻辑中的任何错误或缺陷,我会尽快进行编辑。
Execute
就可以无限地向下进入层次结构了)。实际需求是任何人都可以在任何支持正则表达式的 IDE/编辑器中进行搜索和替换,而不是为了相同的目的编写循环... 在这个 rubular 中,每次匹配只显示 3 个结果而不是 6 个,其中有 3 个为空,这样做更有意义,对吗? - Armfoot