Поиск подстроки с фиксированным концом

Я хотел бы найти подстроку, которая заканчивается после определенной фразы в коллекции (перечисленной в столбце Excel) других строк.

Итак, скажем, я хочу найти строку «BLUE MOON» в других строках, и я хочу определить, что подстрока заканчивается после «N» в «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

person EDC    schedule 11.08.2015    source источник


Ответы (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

Если вы хотите, чтобы строка заканчивалась после "MOON" без каких-либо дополнительных действий, вместо этого включите в шаблон якорь конца строки ($):

re.Pattern = "\bBLUE MOON$"
person Bond    schedule 11.08.2015
comment
это именно то, что я искал. Не знал, что существуют регулярные выражения :) Спасибо, сэр! - person EDC; 11.08.2015
comment
1 короткий дополнительный вопрос: если я использую \b в начале, он работает нормально, например, правильно соответствует DARK BLUE MOON; однако он также соответствует DARK.BLUE MOON. Есть ли способ определить любой случайный шаблон, за которым следует пробел, за которым следует СИНЯЯ ЛУНА? Я провел некоторое тестирование на основе stackoverflow.com/questions/22542834, но пока это не сработало. - person EDC; 12.08.2015
comment
Верно. . считается границей слова. Если вы хотите сопоставить только те случаи, когда перед BLUE есть пробел или это начало строки, вы можете использовать следующий шаблон: (^|\s)BLUE MOON\b. См. regex101 здесь. - person Bond; 12.08.2015