【问题标题】:Searching for a substring with a fixed end搜索具有固定结尾的子字符串
【发布时间】:2015-11-03 23:39:40
【问题描述】:

我想在其他字符串的集合(在 Excel 列中列出)中搜索以某个短语结尾的子字符串。

假设我想在其他字符串中搜索字符串“BLUE MOON”,并且我想确定子字符串在“BLUE MOON”的“N”之后结束,以避免结果为 TRUE,例如“蓝月光”。换句话说,我需要的是搜索单词的任何部分,但仅限于左手。右手边应该有一个固定的边框,即零个附加字符。 另一方面,如果开头不同,我需要积极的结果,例如“DARK BLUE MOON”应该导致 TRUE。因此,完全平等不是一种选择。

我想使用Find,但我相信这是不可能的。 Find似乎不接受除*之外的任何通配符。

这里有一些词供你测试:

  1. 预期搜索结果为阳性:

    BLUE MOON
    DARK BLUE MOON
    LIGHT BLUE MOON
    
  2. 预期的搜索结果是否定的::

    BLUE MOONLIGHT
    LAST BLUE MOONSHINE
    BLUE MOONDANCE
    

任何提示也表示赞赏。现在我正在使用以下函数来删除单词(工作正常,除了它还删除了前面提到的带有负面预期搜索结果的案例):

Sub testingXXX()

Dim ws As Worksheet
Set ws = ActiveWorkbook.ActiveSheet

Dim aCell As Range, bCell As Range, aSave As String, y As Long

MyAr = Split("*BLUE MOON", ",")

 For y = LBound(MyAr) To UBound(MyAr)
      With ws
         Set aCell = .Columns(1).Find(what:=MyAr(y), LookIn:=xlValues, _
                          lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
                          MatchCase:=False, SearchFormat:=False)

         If Not aCell Is Nothing Then
             aSave = aCell.Address
             Do
                 If bCell Is Nothing Then
                     Set bCell = .Range("A" & aCell.row)
                 Else
                     Set bCell = Union(bCell, .Range("A" & aCell.row))
                 End If

                 Set aCell = .Columns(1).FindNext(after:=aCell)

             Loop Until aCell.Address = aSave
         End If

         Set aCell = Nothing
     End With

 Next y

 If Not bCell Is Nothing Then bCell.EntireRow.Delete

End Sub

【问题讨论】:

    标签: string vba search text wildcard


    【解决方案1】:

    这就是发明正则表达式的原因。如果您使用\b 指定单词边框,则只会匹配确切的短语"BLUE MOON",不允许使用其他字符。以下将匹配包含"BLUE MOON" 的字符串:

    Const PHRASES As String = "BLUE MOON,DARK BLUE MOON,LIGHT BLUE MOON,BLUE MOONLIGHT,LAST BLUE MOONSHINE,BLUE MOONDANCE"
    
    Dim re
    Set re = CreateObject("VBScript.RegExp")
    re.Pattern = "\bBLUE MOON\b"
    
    Dim w
    For Each w In Split(PHRASES, ",")
    
        If re.Test(w) Then
            Debug.Print w & " = Match"
        Else
            Debug.Print w & " = No match"
        End If
    
    Next
    

    输出(对齐以便于阅读):

    BLUE MOON           = Match
    DARK BLUE MOON      = Match
    LIGHT BLUE MOON     = Match
    BLUE MOONLIGHT      = No match
    LAST BLUE MOONSHINE = No match
    BLUE MOONDANCE      = No match
    

    如果您想确保字符串 ends"MOON" 之后且完全没有任何附加内容,请在您的模式中包含字符串结尾锚 ($):

    re.Pattern = "\bBLUE MOON$"
    

    【讨论】:

    • 这正是我想要的。不知道存在正则表达式 :) 谢谢先生!
    • 1 个简短的后续问题:如果我在开始时使用\b,它可以正常工作,例如正确匹配 DARK BLUE MOON;但是它也匹配 DARK.BLUE MOON。有没有办法定义任何随机模式,后跟一个空格,然后是 BLUE MOON?我根据stackoverflow.com/questions/22542834做了一些测试,但是目前还不行
    • 对。 . 被认为是一个单词边框。如果您只想匹配BLUE 之前有空格或者它是字符串开头的情况,您可以使用以下模式:(^|\s)BLUE MOON\b。请参阅 regex101 here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    • 2017-07-04
    • 2018-08-24
    相关资源
    最近更新 更多