Я пытаюсь построить шаблон регулярного выражения для такого текста
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 Все нормально как для контры, но не как для мафо
Большое спасибо. В этом случае с вашим шаблоном можно ли будет извлечь каждое число в столбец (особенно последний), поскольку я попробовал шаблон на регулярном выражении101, и число в последней строке появилось в другом цвете. Как я могу сделать две части contra и mafo необязательными и в то же время упростить использование кода для разделения на нужный столбец?
Совет contra?
делает необязательным только последний символ (a
). Если вы хотите, чтобы все слово было необязательным, используйте круглые скобки: (contra)?
.
На самом деле я потерян. Мне нужен шаблон регулярного выражения, чтобы сосредоточиться на строках contra
и mafo
, и мне нужны числа, относящиеся к каждому из них. Проблема в том, что у меня много возможностей: может быть сначала два контра, а потом мафо, или два мафо сначала, а потом контра, а иногда просто контра, а не мафо, а иногда просто мафо, а не контра. Поэтому я пытаюсь найти способ поглотить все эти возможности.
Я думаю, что ключ здесь в том, чтобы заставить ваше регулярное выражение делать меньше, а ваш 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 содержит каждую группу захвата. Вы должны быть в состоянии написать свою собственную логику в этом цикле обработки, чтобы интерпретировать то, что было извлечено. Когда я запустил его на ваших данных, он создал все поля синим цветом:
Обратите внимание, что я добавил к вашим данным строку с двумя контра-записями и одной мафо, и она нашла все вхождения. Вы должны быть в состоянии изменить это, чтобы интерпретировать значения.
Удивительно. Не могли бы вы добавить объяснение шаблона регулярного выражения, чтобы учиться у вас?
ОК - Первые скобки содержат (?:^|[^A-Z])
- это немного хак, потому что VBA не имеет просмотра назад. Это делается для того, чтобы убедиться, что мы не совпадаем с xyzzymafo: 1.3. (?: говорит сканеру регулярных выражений не захватывать это как пронумерованную группу. Следующие парные скобки - это (?:(mafo)|(contra))
, что говорит о том, чтобы принять mafo (в группе захвата 1) ИЛИ против (в группе захвата 2). Затем [^A-Z]\s*
- это некоторая не-альфа, за которой следует ноль или более пробелов. Наконец, (\d*\.?\d+)
— это базовый шаблон захвата чисел в группу захвата 3. Он не примет 123456. как допустимое число, но все остальное должно быть в порядке.
Я бы не стал усложнять регулярное выражение. Вместо этого, когда вы перебираете MatchCollection, введите что-то вроде If IsEmpty(match.subMatches(0)) Then contradigits = match.subMatches(2) Else mafodigits = match.subMatches(2) End If
. затем, когда вы дойдете до конца MatchCollection, вы их разберете. Но только вы можете предоставить дополнительную логику для интерпретации того, что на самом деле означает одно без другого.
Последний вопрос: у меня есть еще один термин мафо — kht
. Как я могу реализовать оба в шаблоне регулярного выражения? Только один из них будет присутствовать в тексте.
Не могли бы вы взглянуть на эту ссылку regex101.com/r/cB36RO/1 Я не мог понять, почему числа до десятичной точки не включены?
Используйте чередование,
contra?.\s+?(\d*\.?\d+)(.+mafo.?\s+(\d*\.?\d+))?|mafo.?\s+(\d*\.?\d+)