【问题标题】:Regex capturing multiple distinct occurence of string pattern正则表达式捕获字符串模式的多个不同出现
【发布时间】:2017-10-14 16:54:16
【问题描述】:

我正在尝试捕获文本中的所有产品代码。它们有时是多个。我只能抓到一个。我想它更多的是 excel vba 问题而不是正则表达式,因为我有 str 模式。

 Sub regexp()

Dim regEx As New regexp
Dim strPattern As String
Dim Myrange As Range
Dim LastRow As Integer


LastRow = ActiveSheet.Cells(Rows.Count, "W").End(xlUp).Row
Set Myrange = ActiveSheet.Range("W4:W" & LastRow)

For Each c In Myrange


strPattern = "(?:\s[ABCDabcd][0-9][A-Za-z0-9]{3}\s|\s[ABCDabcd][0-9oO][0-9oO)][0-9][0-9A-Za-z]\s|\s[ABCDabcd][0-9oO][0-9A-Za-z)][0-9A-Za-z][0-9]\s|[^A-Za-z0-9][ABCDabcd]\s[0-9][A-Z0-9a-z]{3}\s)"
    If strPattern <> "" Then
        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = strPattern
        End With

        Set matches = regEx.Execute(c.Value)
        On Error Resume Next
        c.Offset(0, 7).Value = matches.Item(0)
    End If
Next c
End Sub

如何更改代码以捕获文本中不同的多个字符串模式。此代码当前仅捕获第一个。我想用逗号分隔所有内容。 例如,首先我遇到了产品 b0067 的问题。然后问题就解决了。后来我遇到了这个 D0887 的问题。紧随其后的是 C689W、D 7890 输出 - b0067、D0887、C689W、D 7890 我想修剪这些,因为空格是在结尾或开头考虑的。

【问题讨论】:

  • 您只需使用第一项 - matches.Item(0)。遍历集合并将数据输出到您想要的位置。您想在哪里输出匹配项?但是,我也认为你的模式很慢,因为你的替代方案没有优化。您也可能无法从 " A0ABC B0ABC " 字符串中提取 2 个值。你真的需要在最后匹配一个空格,还是只检查是否有空格?
  • 我现在使用 c.offset(0,7) 在 AD 列中的 7 列之后输出。数据很混乱,所以想理想地捕获 5 个字符,但我认为最好的方法是 \s,但如果它们以句号结尾,我会错过。”

标签: regex excel vba


【解决方案1】:

首先,我建议将正则表达式增强为

strPattern = "(?:\s[abcd](?:[0-9][a-z0-9]{3}|[0-9o][0-9o)][0-9][0-9a-z]|[0-9o][0-9a-z)][0-9a-z][0-9])|[^a-z0-9][abcd]\s[0-9][0-9a-z]{3})(?!\S)"

请参阅regex demo确保您设置了.IgnoreCase = True。此正则表达式将检查匹配后是否有空格或字符串结尾与(?!\S) 前瞻,因此A0ABCB0ABC 将从"1 A0ABC B0ABC 3" 中提取。第一个 \s 可以更改为 (^|\s) 以匹配字符串开头的字符串。

然后,在运行 Execute() 之后,遍历匹配项:

 Set matches = regEx.Execute(c.Value)
 For Each m In matches
    Cells(x, y) = m.Value
 Next

这是一个完整的固定sub,它将以逗号分隔值的形式将匹配项打印到您指定的单元格:

Dim regEx As New regexp
Dim strPattern As String
Dim Myrange As Range
Dim LastRow As Long, cnt As Long

LastRow = ActiveSheet.Cells(Rows.Count, "W").End(xlUp).Row
Set Myrange = ActiveSheet.Range("W4:W" & LastRow)
strPattern = "(?:\s[abcd](?:[0-9][a-z0-9]{3}|[0-9o][0-9o)][0-9][0-9a-z]|[0-9o][0-9a-z)][0-9a-z][0-9])|[^a-z0-9][abcd]\s[0-9][0-9a-z]{3})(?!\S)"

If strPattern <> "" Then
  With regEx
    .Global = True
    .IgnoreCase = True
    .Pattern = strPattern
  End With
  cnt = 0
  For Each c In Myrange
    Set matches = regEx.Execute(c.Value)
    For Each m In matches
        c.Offset(0, 7).Value = c.offset(0, 7).Value + m.Value
        cnt = cnt + 1
        If cnt < matches.Count Then c.offset(0, 7) = c.offset(0, 7) & ","
    Next
  Next c
End If

注意 RegExp 的初始化位置 - 在循环之外。

【讨论】:

  • 我恢复了演示的链接(带有 PCRE 设置),以便可以忽略格式。
  • y 应该是 30(AD 列)我的 x 值应该是多少以及我应该如何更改 x 值
  • @viji:我认为打印值没有问题。您可以使用计数器并在每次从集合中检索到新值时递增它。然后增加行或列值。
  • 对不起,我不明白。我想在 AD 列中查看以逗号分隔的每个相应字符串的结果。在我上面的示例中,W 是我的字符串所在的位置,如果它们出现在 AD 中的字符串中,我想查看多个值,它们用逗号分隔
  • @viji:查看完整的固定子。
猜你喜欢
  • 2021-01-15
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 2012-08-20
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
相关资源
最近更新 更多