从字符串中提取最大的数字序列(正则表达式,或?)
Extract largest numeric sequence from string (regex, or?)
我有类似于以下的字符串:
4123499-TESCO45-123
every99999994_54
而我想提取每个字符串中最大的数字序列,分别为:
4123499
99999994
我之前尝试过正则表达式(我使用的是 VB6)
Set rx = New RegExp
rx.Pattern = "[^\d]"
rx.Global = True
StringText = rx.Replace(StringText, "")
这让我走到了一半,但它只删除了非数字值,我最终得到的第一个字符串如下所示:
412349945123
我能否找到满足我要求的正则表达式,还是我必须尝试其他方法?本质上,我的模式必须是任何不是最长数字序列的东西。但我实际上不确定这是否是一个合理的模式。有更好的正则表达式处理能力的人能告诉我我是否陷入困境吗?感谢您的帮助!
您无法仅通过正则表达式获得结果。您将不得不提取所有数字块并使用其他编程方法获得最长的一个。
这是一个例子:
Dim strPattern As String: strPattern = "\d+"
Dim str As String: str = "4123499-TESCO45-123"
Dim regEx As New RegExp
Dim matches As MatchCollection
Dim match As Match
Dim result As String
With regEx
.Global = True
.MultiLine = False
.IgnoreCase = False
.Pattern = strPattern
End With
Set matches = regEx.Execute(str)
For Each m In matches
If result < Len(m.Value) Then result = m.Value
Next
Debug.Print result
\d+
和RegExp.Global=True
会找到所有的数字块,然后在循环处理所有匹配后只打印最长的。
单独使用 RE 无法解决这个问题。
相反,您可以简单地沿着字符串走,跟踪最长的连续数字组:
For i = 1 To Len(StringText)
If IsNumeric(Mid$(StringText, i, 1)) Then
a = a & Mid$(StringText, i, 1)
Else
a = ""
End If
If Len(a) > Len(longest) Then longest = a
Next
MsgBox longest
(第一个结果为平局)
如果你给出的两个例子是标准的,其中:
<long_number>-<some_other_data>-<short_number>
<text><long_number>_<short_number>
字符串进来的两种格式,有一些解决方法。
但是,如果您在任何格式的任何字符串中搜索最长的数字,这些将不起作用。
解决方案 1
([0-9]+)[_-].*
见demo
在第一个捕获组中,您应该拥有这 2 种格式的最长编号。
注意:这假定最长的数字将是它遇到的第一个数字,旁边有下划线或连字符,与给定的两个示例相匹配。
解决方案 2
\d{6,}
见demo
注意:这里假设最短的数字长度永远不会超过5个字符,最长的数字长度永远不会短于6个字符
拜托,试试。
纯VB。 没有外部库或对象。
没有 brain-breaking 正则表达式的模式。
没有字符串操作,所以 - 速度。 超高速。 比 快 ~30 倍 :)
轻松转换各种需求。
例如,将源字符串中的所有数字连接成一个字符串。
此外,如果目标字符串只是中间步骤,
所以可以只用数字来操作。
Public Sub sb_BigNmb()
Dim sSrc$, sTgt$
Dim taSrc() As Byte, taTgt() As Byte, tLB As Byte, tUB As Byte
Dim s As Byte, t As Byte, tLenMin As Byte
tLenMin = 4
sSrc = "every99999994_54"
sTgt = vbNullString
taSrc = StrConv(sSrc, vbFromUnicode)
tLB = LBound(taSrc)
tUB = UBound(taSrc)
ReDim taTgt(tLB To tUB)
t = 0
For s = tLB To tUB
Select Case taSrc(s)
Case 48 To 57
taTgt(t) = taSrc(s)
t = t + 1
Case Else
If CBool(t) Then Exit For ' *** EXIT FOR ***
End Select
Next
If (t > tLenMin) Then
ReDim Preserve taTgt(tLB To (t - 1))
sTgt = StrConv(taTgt, vbUnicode)
End If
Debug.Print "'" & sTgt & "'"
Stop
End Sub
如何处理sSrc = "ev_1_ery99999994_54"
,请自行制作:)
.
我有类似于以下的字符串:
4123499-TESCO45-123
every99999994_54
而我想提取每个字符串中最大的数字序列,分别为:
4123499
99999994
我之前尝试过正则表达式(我使用的是 VB6)
Set rx = New RegExp
rx.Pattern = "[^\d]"
rx.Global = True
StringText = rx.Replace(StringText, "")
这让我走到了一半,但它只删除了非数字值,我最终得到的第一个字符串如下所示:
412349945123
我能否找到满足我要求的正则表达式,还是我必须尝试其他方法?本质上,我的模式必须是任何不是最长数字序列的东西。但我实际上不确定这是否是一个合理的模式。有更好的正则表达式处理能力的人能告诉我我是否陷入困境吗?感谢您的帮助!
您无法仅通过正则表达式获得结果。您将不得不提取所有数字块并使用其他编程方法获得最长的一个。
这是一个例子:
Dim strPattern As String: strPattern = "\d+"
Dim str As String: str = "4123499-TESCO45-123"
Dim regEx As New RegExp
Dim matches As MatchCollection
Dim match As Match
Dim result As String
With regEx
.Global = True
.MultiLine = False
.IgnoreCase = False
.Pattern = strPattern
End With
Set matches = regEx.Execute(str)
For Each m In matches
If result < Len(m.Value) Then result = m.Value
Next
Debug.Print result
\d+
和RegExp.Global=True
会找到所有的数字块,然后在循环处理所有匹配后只打印最长的。
单独使用 RE 无法解决这个问题。
相反,您可以简单地沿着字符串走,跟踪最长的连续数字组:
For i = 1 To Len(StringText)
If IsNumeric(Mid$(StringText, i, 1)) Then
a = a & Mid$(StringText, i, 1)
Else
a = ""
End If
If Len(a) > Len(longest) Then longest = a
Next
MsgBox longest
(第一个结果为平局)
如果你给出的两个例子是标准的,其中:
<long_number>-<some_other_data>-<short_number>
<text><long_number>_<short_number>
字符串进来的两种格式,有一些解决方法。
但是,如果您在任何格式的任何字符串中搜索最长的数字,这些将不起作用。
解决方案 1
([0-9]+)[_-].*
见demo
在第一个捕获组中,您应该拥有这 2 种格式的最长编号。
注意:这假定最长的数字将是它遇到的第一个数字,旁边有下划线或连字符,与给定的两个示例相匹配。
解决方案 2
\d{6,}
见demo
注意:这里假设最短的数字长度永远不会超过5个字符,最长的数字长度永远不会短于6个字符
拜托,试试。
纯VB。 没有外部库或对象。
没有 brain-breaking 正则表达式的模式。
没有字符串操作,所以 - 速度。 超高速。 比
轻松转换各种需求。
例如,将源字符串中的所有数字连接成一个字符串。
此外,如果目标字符串只是中间步骤,
所以可以只用数字来操作。
Public Sub sb_BigNmb()
Dim sSrc$, sTgt$
Dim taSrc() As Byte, taTgt() As Byte, tLB As Byte, tUB As Byte
Dim s As Byte, t As Byte, tLenMin As Byte
tLenMin = 4
sSrc = "every99999994_54"
sTgt = vbNullString
taSrc = StrConv(sSrc, vbFromUnicode)
tLB = LBound(taSrc)
tUB = UBound(taSrc)
ReDim taTgt(tLB To tUB)
t = 0
For s = tLB To tUB
Select Case taSrc(s)
Case 48 To 57
taTgt(t) = taSrc(s)
t = t + 1
Case Else
If CBool(t) Then Exit For ' *** EXIT FOR ***
End Select
Next
If (t > tLenMin) Then
ReDim Preserve taTgt(tLB To (t - 1))
sTgt = StrConv(taTgt, vbUnicode)
End If
Debug.Print "'" & sTgt & "'"
Stop
End Sub
如何处理sSrc = "ev_1_ery99999994_54"
,请自行制作:)
.