(如果您对介绍无聊,可以跳到如果......,该怎么办)
这个问题不是特别针对VBScript的(在这种情况下,我只是使用了它):我想找到一种解决常规正则表达式用法的方法(包括编辑器)。
当我想创建示例4的改编版本时,它开始了,其中3个捕获组用于在MS Excel中将数据拆分为3个单元格。我需要捕获一个完整的模式,然后在其中捕获其他三个模式。但是,在同一个表达式中,我还需要捕获另一种模式,并再次捕获其中的3种其他模式(是的,我知道...但是在指着裸露的手指之前,请先完成阅读)。
我首先想到了命名捕获组,然后我意识到我不应该“混合命名和编号的捕获组”,因为不建议使用“混合命名和编号的风味,因为它们的编号方式不一致”。
然后,我研究了VBScript子匹配和“非捕获”组,并得到了针对特定情况的有效解决方案:
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
这是正则表达式的Rubular中的演示。在这些:
124; 12; 3
我的id1:213我的id2:232我的词:ins4yanrgx
:8587459:18254182540215:dcpt
0; 1; 2
它返回前两个带有数字的单元格,第三个返回带有数字或单词的单元格。基本上,我使用了一个非捕获组,该组具有2个“父”模式(“父” =我要检测其他子模式的广泛模式)。如果1个ST父图案具有匹配子图案(1个ST捕获组),那么我将其值与在3个细胞这个图案的剩余捕获基团。如果不匹配,则检查第四个捕获组(属于第二个父模式)是否匹配,并将其余的子模式放在相同的3个单元格中。
而不是像这样:
(?:^(\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
它会匹配:特殊
如果您发现此逻辑中有任何错误或缺陷,请告诉我,我将尽快进行编辑。
通常是要捕获几乎相同的数据的情况。
唯一的区别在于形式。
有一个用于分支重置的正则表达式构造。
它在大多数与Perl兼容的引擎上提供。不是Java也不是Dot Net。
它主要是节省正则表达式资源,并使匹配更容易。
您提到的替代方法无济于事,它实际上只是使用
更多的资源。您仍然必须查看匹配项以了解您的位置。
但是,您只需要检查集群中的一个组即可知道其他哪些
组有效(<-如果使用分支重置,则没有必要)。
(下面是使用 RegexFormat 6构造的)
这是分支重置版本:
# (?|^(\d+);(\d+);(\d+)$|^.*:(\d+)\s.*:(\d+).*:(\w+)$|what(ever)()())
(?|
^
( \d+ ) # (1)
;
( \d+ ) # (2)
;
( \d+ ) # (3)
$
|
^ .* :
( \d+ ) # (1)
\s .* :
( \d+ ) # (2)
.* :
( \w+ ) # (3)
$
|
what
( ever ) # (1)
( ) # (2)
( ) # (3)
)
这是您的两个正则表达式。请注意,“父级”捕获实际上增加了组的数量(这降低了引擎的速度):
# (?:^(\d+);(\d+);(\d+)$|^.*:(\d+)\s.*:(\d+).*:(\w+)$|what(ever))
(?:
^
( \d+ ) # (1)
;
( \d+ ) # (2)
;
( \d+ ) # (3)
$
|
^ .* :
( \d+ ) # (4)
\s .* :
( \d+ ) # (5)
.* :
( \w+ ) # (6)
$
|
what
( ever ) # (7)
)
和
# (#:^(\d+);(\d+);(\d+)$)|(#:^.*:(\d+)\s.*:(\d+).*:(\w+)$)|(#:what(ever))
( # (1 start)
\#: ^
( \d+ ) # (2)
;
( \d+ ) # (3)
;
( \d+ ) # (4)
$
) # (1 end)
|
( # (5 start)
\#: ^ .* :
( \d+ ) # (6)
\s .* :
( \d+ ) # (7)
.* :
( \w+ ) # (8)
$
) # (5 end)
|
( # (9 start)
\#:what
( ever ) # (10)
) # (9 end)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句