Могу ли я использовать регулярные выражения, оператор Like и / или Instr (), чтобы найти индекс шаблона в большей строке? - PullRequest
1 голос
/ 16 января 2020

У меня большой список (таблица с одним полем) нестандартизированных строк, импортированных из плохо управляемой устаревшей базы данных. Мне нужно извлечь одиночное число di git (заключенное в пробелы), которое встречается ровно один раз в каждой из этих строк (хотя иногда строки имеют и другие числа multi-di git). Например, из следующей строки:

"Quality Assurance File System And Records Retention Johnson, R.M. 004 4 2999 ss/ds/free ReviewMo = Aug Effective 1/31/2012 FileOpen-?"

Я хотел бы получить число 4 (или 4-х позиционное значение в строке, т.е. 71)

Я могу использовать

WHERE rsLegacyList.F1 LIKE "* # *" 

внутри оператора select, чтобы найти , если каждая строка имеет одиночный ди git, и, таким образом, отфильтровать мой список. Но это не говорит мне , где - это di git, поэтому я могу извлечь сам di git (с функцией mid()) и начать сортировку списка. Цель состоит в том, чтобы создать второе поле с этим di git само по себе как метод сортировки больших строк в первом поле.

Есть ли способ использовать Instr() вместе с регулярными выражениями, чтобы найти, где регулярное выражение встречается в большей строке? Что-то вроде

intMarkerLocation = instr(rsLegacyList.F1, Like "* # *")

, но на самом деле это работает?

Я ценю любые предложения или обходные пути, которые полностью решают проблему.


@ Lee Ma c Я сделал функцию RegExFindStringIndex, как показано здесь:

Public Function RegExFindStringIndex(strToSearch As String, strPatternToMatch As String) As Integer

    Dim regex                       As RegExp
    Dim Matching                    As Match

    Set regex = New RegExp

    With regex
        .MultiLine = False
        .Global = True
        .IgnoreCase = False
        .Pattern = strPatternToMatch
        Matching = .Execute(strToSearch)
        RegExFindStringIndex = Matching.FirstIndex
    End With

    Set regex = Nothing
    Set Matching = Nothing
End Function

Но это дает мне ошибку Неправильное использование свойства в строке Matching = .Execute(strToSearch)

Ответы [ 2 ]

1 голос
/ 16 января 2020

Использование регулярных выражений

Если бы вы использовали регулярные выражения, вам нужно было бы определить функцию VBA для создания экземпляра объекта RegExp, установить для свойства pattern что-то вроде \s\d\s (whitespace-di git -пробел), а затем вызовите метод Execute, чтобы получить совпадение (или совпадения), каждый из которых предоставит индекс шаблона в строке. Если вы хотите следовать этому маршруту, здесь - это некоторые существующие примеры для Excel, но манипуляции с RegExp будут идентичны в MS Access.

Вот пример функции, демонстрирующей, как использовать первый результат, возвращаемый методом Execute:

Public Function RegexInStr(strStr As String, strPat As String) As Integer
    With New RegExp
        .Multiline = False
        .Global = True
        .IgnoreCase = False
        .Pattern = strPat
        With .Execute(strStr)
            If .Count > 0 Then RegexInStr = .Item(0).FirstIndex + 1
        End With
    End With
End Function

Обратите внимание, что в вышеприведенном примере используется раннее связывание, поэтому вам необходимо добавить ссылку на библиотеку Microsoft VBScript Regular Expressions 5.5 в свой файл. project.

Пример оценки немедленного окна:

?InStr("abc 1 123", " 1 ")
 4 
?RegexInStr("abc 1 123", "\s\w\s")
 4 

Использование InStr

Альтернатива с использованием встроенного instr Функция в запросе может быть следующим не элегантным (и, вероятно, очень медленным) запросом:

select
    switch
    (
        instr(rsLegacyList.F1," 0 ")>0,instr(rsLegacyList.F1," 0 ")+1,
        instr(rsLegacyList.F1," 1 ")>0,instr(rsLegacyList.F1," 1 ")+1,
        instr(rsLegacyList.F1," 2 ")>0,instr(rsLegacyList.F1," 2 ")+1,
        instr(rsLegacyList.F1," 3 ")>0,instr(rsLegacyList.F1," 3 ")+1,
        instr(rsLegacyList.F1," 4 ")>0,instr(rsLegacyList.F1," 4 ")+1,
        instr(rsLegacyList.F1," 5 ")>0,instr(rsLegacyList.F1," 5 ")+1,
        instr(rsLegacyList.F1," 6 ")>0,instr(rsLegacyList.F1," 6 ")+1,
        instr(rsLegacyList.F1," 7 ")>0,instr(rsLegacyList.F1," 7 ")+1,
        instr(rsLegacyList.F1," 8 ")>0,instr(rsLegacyList.F1," 8 ")+1,
        instr(rsLegacyList.F1," 9 ")>0,instr(rsLegacyList.F1," 9 ")+1,
        true, null
    ) as intMarkerLocation
from
    rsLegacyList
where 
    rsLegacyList.F1 like "* # *" 
0 голосов
/ 16 января 2020

Как насчет:

select
    instr(rsLegacyList.F1, " # ") + 1 as position
from rsLegacyList.F1
where rsLegacyList.F1 LIKE "* # *"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...