[英]Regex match no groups, 1st group OR 2nd group but not both. Something like 'NAND'
[英]Regex lookahead to match everything prior to 1st OR 2nd group of digits
VBA中的正则表达式。
我正在使用以下正则表达式来匹配4位数字组的第二次出现,如果只有一个组,则匹配第一组:
\b\d{4}\b(?!.+\b\d{4}\b)
现在,我需要做相反的事情:我需要匹配所有内容,直到出现第二个4位数组,或者如果只有一个,则匹配到第一组。 如果没有4位数字组,则捕获整个字符串。
这样就足够了。
但是,还有一条更可取的“加分”路线:如果存在一种方法来匹配所有内容,直到一个4位数字组,然后可选地跟随一些随机文本,但前提是后面没有其他4位数字组。 如果存在第二组4位数字,则捕获直到该组为止的所有内容(包括第一组和句号,但不包括逗号)。 如果没有组,则捕获所有内容。 如果该行以4位数字组开头,则不捕获任何内容。
我知道也可以(应该?)先行完成,但是我没有运气来弄清楚它们如何为此目的工作。
例子:
Input: String.String String 4444
Capture: String.String String 4444
Input: String4444 8888 String
Capture: String4444
Input: String String 444 . B, 8888
Capture: String String 444 . B
奖励情况:
Input: 8888 String
Capture:
对于您的基本情况(由您标记为足够),这将起作用:
((?:(?!\d{4}).)*(?:\d{4})?(?:(?!\d{4}).)*)(?=\d{4})
如果需要,可以在内部用\\b
填充每个\\d{4}
。
在此处查看演示。
您可以在VBA中使用此正则表达式捕获具有4位数字的行或其中没有4位数字的行:
^((?:.*?[0-9]{4})?.*?(?=\s*?[0-9]{4})|(?!.*[0-9]{4}).*)
参见demo ,它在VBA中应该可以正常工作。
正则表达式由2个选择组成: (?:.*?[0-9]{4})?.*?(?=\\s*?[0-9]{4})
和(?!.*[0-9]{4}).*
。
(?:.*?[0-9]{4})?.*?(?=\\s*?[0-9]{4})
匹配0个或更多(尽可能少)的字符0或1个字符序列,后跟一个4位数字,然后是可选的空格和4位数字。
(?!.*[0-9]{4}).*
匹配内部没有4位数字的任意数量的字符。
请注意,仅匹配整数(不包括其他部分),您需要在[0-9]{4}
模式(即\\b[0-9]{4}\\b
)周围添加\\b
。
如果有人感兴趣,我会作弊以完全解决我的问题。
基于此答案 (它解决了我的绝大多数数据集),我使用程序逻辑来捕获一些罕见的用例。 似乎很难获得一个正则表达式来涵盖所有情况,因此这似乎是一个可行的选择。
问题在这里说明。
该代码还不是防弹的,但这是要点:
Function cRegEx (str As String) As String
Dim rExp As Object, rMatch As Object, regP As String, strL() As String
regP = "^((?:.*?[0-9]{4})?.*?(?:(?=\s*[0-9]{4})|(?:(?!\d{4}).)*)|(?!.*[0-9]{4}).*)"
' Encountered two use-cases that weren't easily solvable with regex, due to the already complex pattern(s).
' Split str if we encounter a comma and only keep the first part - this way we don't have to solve this case in the regex.
If InStr(str, ",") <> 0 Then
strL = Split(str, ",")
str = strL(0)
End If
' If str starts with a 4-digit group, return an empty string.
If cRegExNum(str) = False Then
Set rExp = CreateObject("vbscript.regexp")
With rExp
.Global = False
.MultiLine = False
.IgnoreCase = True
.Pattern = regP
End With
Set rMatch = rExp.Execute(str)
If rMatch.Count > 0 Then
cRegEx = rMatch(0)
Else
cRegEx = ""
End If
Else
cRegEx = ""
End If
End Function
Function cRegExNum (str As String) As Boolean
' Does the string start with 4 non-whitespaced integers?
' Return true if it does
Dim rExp As Object, rMatch As Object, regP As String
regP = "^\d{4}"
Set rExp = CreateObject("vbscript.regexp")
With rExp
.Global = False
.MultiLine = False
.IgnoreCase = True
.Pattern = regP
End With
Set rMatch = rExp.Execute(str)
If rMatch.Count > 0 Then
cRegExNum = True
Else
cRegExNum = False
End If
End Function
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.