首页 > 解决方案 > 如何使用 RegEx 从字符串中删除某些单词

问题描述

我需要清理一些单元格,只保留重要的单词来生成搜索索引。

例如。“如何提出帐户恢复请求”将被修剪为“提出帐户恢复请求”,因为“How, To, An”将在要过滤掉的单词列表中。

另一个复杂性是它也将是法语和西班牙语,这意味着我必须处理像 d' 这样的部分词。

到目前为止,我一直在尝试使用一个函数,但它不适用于部分词(d'),如果“de”和“des”列在同一个单元格中,它将从 DES 中删除 DE,然后只保留孤独的 S,因为不再识别 DES:

Function ClearWords(s As String, rWords As Range) As String
Static RX As Object

If RX Is Nothing Then
    Set RX = CreateObject("VBScript.RegExp")
    RX.Global = True
    RX.IgnoreCase = True
End If

RX.Pattern = "\b" & Replace(Join(Application.Transpose(rWords), "|"), ".", "\.") & "\b"

ClearWords = Application.Trim(RX.Replace(s, ""))
End Function

标签: regexexcelvba

解决方案


如果您计划支持英语、法语和其他欧洲语言,您可以利用我在Regular expression not working for at least one European character 中 发布的正则表达式,(?![×÷])[A-Za-zÀ-ÿ]. 这是一个应该匹配您需要支持的所有字母字符的模式。\uXXXX由于您将在 VBA 中使用它,因此将文字扩展字母替换为实体并将其转换为单个字符类[A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF][A-Za-zÀ-ÖØ-öø-ÿ]使用文字字符)是有意义的。

现在,您需要构建自定义边界。初始边界要么是字符串的开头,要么是^除上述字母之外的任何字符(_如果您想完全模拟,也可能是数字和\b)。既然要替换,就需要将这两个模式放到一个(^|[^A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]) 捕获组中,并$1在替换模式中使用来恢复值,以免丢失。尾随边界是除上面的字母(或数字 / _)和字符串结尾之外的任何字符。由于 VBA 正则表达式支持前瞻,我们可以只使用负前瞻(?![A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]).

把它放在一起:

RX.Pattern = "(^|[^A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF])(?:" & Replace(Join(Application.Transpose(rWords), "|"), ".", "\.") & ")(?![A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF])"
ClearWords = Application.Trim(RX.Replace(s, "$1"))

请参阅此正则表达式演示

要同时删除之前的空格,请替换"(^|[^A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF])(?:"(?:\s+|(^|[^A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]))(?:. 请参阅此正则表达式演示

奖励:您似乎需要转义这些词才能在正则表达式中使用它们:

Dim regExEscape As New RegExp
With regExEscape
    .pattern = "[-/\\^$*+?.()|[\]{}]"
    .Global = True
    .MultiLine = False
End With

只要确保您处理所有单词而不是Replace(Join(Application.Transpose(rWords), "|"), ".", "\.").


推荐阅读