使用 Regex/VBA 获取每个以点结尾的单词

0 regex excel vba regex-group

在 Office 2019 Excel 电子表格中。我试图从任何指定的单元格中提取最多 5 个以 ] 后的点结尾的单词。

示例文本:

一些文字[asred.] ost。|周一 - 里本(终极)很多。交流,中国。其他可能是长文本;科兰。

我预计:

OST。终极。很多。华。科兰。

我在网上找到了这个功能:

Public Function RegExtract(Txt As String, Pattern As String) As String

With CreateObject("vbscript.regexp")
    '.Global = True
    .Pattern = Pattern
    If .test(Txt) Then
        RegExtract = .Execute(Txt)(0)
    Else
        RegExtract = "No match found"
    End If
End With

End Function
Run Code Online (Sandbox Code Playgroud)

我从一个空单元格中调用它:

=RegExtract(D2; "([\]])(\s\w+[.]){0,5}")
Run Code Online (Sandbox Code Playgroud)

我的表情:

([\]])(\s\w+[.]){0,5}
Run Code Online (Sandbox Code Playgroud)

它返回:

] OST。

  1. 我无法去掉 ] ,因为 \K 在 Excel 中不起作用,因此需要找到有用位在文本块内开始的位置。

  2. 我不明白迭代器如何工作以获取“最多 5 次出现”。
    我预计第二组之后的 {0,5} 表示:重复前一组直到文本块末尾(或者直到您成功执行 5 次)。

--在 JdvD 接受记录答案后添加--

我使用这种模式来获取在第一次出现右括号后以点结尾的所有单词。

^.*?\]|(\w+\.\s?)|.
Run Code Online (Sandbox Code Playgroud)

这个(不带问号)取而代之的是在最后一次出现右括号之后所有以点结尾的单词。

^.*\]|(\w+\.\s?)|.
Run Code Online (Sandbox Code Playgroud)

我的 regExtract 函数中遗漏了一些内容:我需要通过 for 循环将匹配项存储到数组中,然后将该数组作为字符串输出。我假设正则表达式引擎将匹配存储为唯一的字符串。

工作功能:

=RegExtract(D2; "([\]])(\s\w+[.]){0,5}")
Run Code Online (Sandbox Code Playgroud)

Jvd*_*vdV 5

正则表达式匹配:

除了@RonRosenfeld给出的答案之外,还可以应用一些人所说的“有史以来最好的正则表达式技巧”,这意味着首先匹配您想要的内容,然后在捕获组中匹配您想要的内容。例如:

^.*\]|(\w+\.)
Run Code Online (Sandbox Code Playgroud)

请参阅在线演示,简而言之,这意味着:

  • ^.*\]- 匹配从字符串开头到最后出现的右方括号的 0+(贪婪)字符;
  • |- 或者;
  • (\w+\.)- 捕获持有 1+(贪婪)以点结尾的单词字符的组。

以下是它在 UDF 中的工作方式:

Sub Test()

Dim s As String: s = "some text [asred.] ost. |Monday - Ribben (ult.) lot. ac, sino. other maybe long text; collan. "

Debug.Print RegExtract(s, "^.*\]|(\w+\.)")

End Sub

'------

'The above Sub would invoke the below function as an example.
'But you could also invoke this through: `=RegExtract(A1,"^.*\]|(\w+\.)")`
'on your sheet.

'------

Public Function RegExtract(Txt As String, Pattern As String) As String

Dim rMatch As Object, arrayMatches(), i As Long

With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = Pattern
    If .Test(Txt) Then
        For Each rMatch In .Execute(Txt)
            If Not IsEmpty(rMatch.SubMatches(0)) Then
                ReDim Preserve arrayMatches(i)
                arrayMatches(i) = rMatch.SubMatches(0)
                i = i + 1
            End If
        Next
        RegExtract = Join(arrayMatches, " ")
    Else
        RegExtract = "No match found"
    End If
End With

End Function
Run Code Online (Sandbox Code Playgroud)

正则表达式替换:

根据您所需的输出,还可以使用替换功能。您必须将任何剩余字符与另一个替代字符相匹配。例如:

^.*\]|(\w+\.\s?)|.
Run Code Online (Sandbox Code Playgroud)

请参阅在线演示,简而言之,这意味着我们添加了另一种选择,即任何单个角色。第二个小补充是我们在第二个替代方案中添加了可选空格字符的选项\s?

Sub Test()

Dim s As String: s = "some text [asred.] ost. |Monday - Ribben (ult.) lot. ac, sino. other maybe long text; collan. "

Debug.Print RegReplace(s, "^.*\]|(\w+\.\s?)|.", "$1")

End Sub

'------

'There are now 3 parameters to parse to the UDF; String, Pattern and Replacement.

'------

Public Function RegReplace(Txt As String, Pattern As String, Replacement) As String

Dim rMatch As Object, arrayMatches(), i As Long

With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = Pattern
    RegReplace = Trim(.Replace(Txt, Replacement))
End With

End Function
Run Code Online (Sandbox Code Playgroud)

请注意,我曾经Trim()删除可能的尾随空格。


RegexMatch 和 RegexReplace 当前都会返回单个字符串来清理输入,但前者确实为您提供了处理 arrayMatches() 变量中的数组的选项。