Необязательные части шаблона регулярного выражения в vba

Я пытаюсь построить шаблон регулярного выражения для такого текста

numb contra: 1.29151306 number mafo: 66662308
numb contra 1.30789668number mafo 60.046483
numb contra/ 1.29154056 number mafo: 666692638
numb contra     137459625
mafo: 666692638
mafo: 666692638 numb contra/ 1.29154056

Вот шаблон, который я мог построить

contra?.\s+?(\d+\.?\d+)(.+mafo.?\s+(\d+\.?\d+))?

Он отлично работает для всех строк, кроме последней. Как я могу реализовать все возможности, чтобы включить последнюю строку?

Пожалуйста, взгляните на эту ссылку https://regex101.com/r/pSThAU/1 Все нормально как для контры, но не как для мафо

Используйте чередование, contra?.\s+?(\d*\.?\d+)(.+mafo.?\s+(\d*\.?\d+))?|mafo.?\s+(\‌​d*\.?\d+)

Wiktor Stribiżew 22.03.2022 23:49

Большое спасибо. В этом случае с вашим шаблоном можно ли будет извлечь каждое число в столбец (особенно последний), поскольку я попробовал шаблон на регулярном выражении101, и число в последней строке появилось в другом цвете. Как я могу сделать две части contra и mafo необязательными и в то же время упростить использование кода для разделения на нужный столбец?

YasserKhalil 23.03.2022 00:08

Совет contra? делает необязательным только последний символ (a). Если вы хотите, чтобы все слово было необязательным, используйте круглые скобки: (contra)?.

Poul Bak 23.03.2022 00:17

На самом деле я потерян. Мне нужен шаблон регулярного выражения, чтобы сосредоточиться на строках contra и mafo, и мне нужны числа, относящиеся к каждому из них. Проблема в том, что у меня много возможностей: может быть сначала два контра, а потом мафо, или два мафо сначала, а потом контра, а иногда просто контра, а не мафо, а иногда просто мафо, а не контра. Поэтому я пытаюсь найти способ поглотить все эти возможности.

YasserKhalil 23.03.2022 00:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
46
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что ключ здесь в том, чтобы заставить ваше регулярное выражение делать меньше, а ваш vba делать больше. Мне кажется, я вижу здесь либо слово «мафо» или «контра» и число, следующее за ним. Не знаю, в каком порядке или присутствует ли каждый или сколько раз. Таким образом, вы можете сканировать каждую из ваших строк на ВСЕ вхождения с помощью регулярного выражения, подобного этому:

(?:^|[^A-Z])(?:(mafo)|(contra))[^A-Z]\s*(\d*\.?\d+)

Затем обработайте его с помощью некоторого кода VBA, подобного этому, который я создал в Excel:

Sub BreakItUp()
Dim rg As RegExp, scanned As MatchCollection, eachMatch As Match, i As Long, col As Long

Set rg = New RegExp
rg.Pattern = "(?:^|[^A-Z])(?:(mafo)|(contra))[^A-Z]\s*(\d*\.?\d+)"
rg.IgnoreCase = True
rg.Global = True
i = 1
Do While (Not IsEmpty(ActiveSheet.Cells(i, 1).Value))
    Set scanned = rg.Execute(ActiveSheet.Cells(i, 1).Value)
    col = 2
    For Each eachMatch In scanned
        ActiveSheet.Cells(i, col).Value = eachMatch.SubMatches(0) & eachMatch.SubMatches(1)
        ActiveSheet.Cells(i, col + 1).Value2 = "'" & eachMatch.SubMatches(2)
        col = col + 2
    Next eachMatch
    i = i + 1
Loop
End Sub

Этот объект MatchCollection получит один элемент для каждого совпадения, а массив subMatches содержит каждую группу захвата. Вы должны быть в состоянии написать свою собственную логику в этом цикле обработки, чтобы интерпретировать то, что было извлечено. Когда я запустил его на ваших данных, он создал все поля синим цветом:

Обратите внимание, что я добавил к вашим данным строку с двумя контра-записями и одной мафо, и она нашла все вхождения. Вы должны быть в состоянии изменить это, чтобы интерпретировать значения.

Удивительно. Не могли бы вы добавить объяснение шаблона регулярного выражения, чтобы учиться у вас?

YasserKhalil 23.03.2022 06:41

ОК - Первые скобки содержат (?:^|[^A-Z]) - это немного хак, потому что VBA не имеет просмотра назад. Это делается для того, чтобы убедиться, что мы не совпадаем с xyzzymafo: 1.3. (?: говорит сканеру регулярных выражений не захватывать это как пронумерованную группу. Следующие парные скобки - это (?:(mafo)|(contra)), что говорит о том, чтобы принять mafo (в группе захвата 1) ИЛИ против (в группе захвата 2). Затем [^A-Z]\s* - это некоторая не-альфа, за которой следует ноль или более пробелов. Наконец, (\d*\.?\d+) — это базовый шаблон захвата чисел в группу захвата 3. Он не примет 123456. как допустимое число, но все остальное должно быть в порядке.

Chris Maurer 23.03.2022 06:51

Я бы не стал усложнять регулярное выражение. Вместо этого, когда вы перебираете MatchCollection, введите что-то вроде If IsEmpty(match.subMatches(0)) Then contradigits = match.subMatches(2) Else mafodigits = match.subMatches(2) End If. затем, когда вы дойдете до конца MatchCollection, вы их разберете. Но только вы можете предоставить дополнительную логику для интерпретации того, что на самом деле означает одно без другого.

Chris Maurer 23.03.2022 07:26

Последний вопрос: у меня есть еще один термин мафо — kht. Как я могу реализовать оба в шаблоне регулярного выражения? Только один из них будет присутствовать в тексте.

YasserKhalil 23.03.2022 07:54

Не могли бы вы взглянуть на эту ссылку regex101.com/r/cB36RO/1 Я не мог понять, почему числа до десятичной точки не включены?

YasserKhalil 23.03.2022 10:23

Другие вопросы по теме