Введение
(вы можете пропустить до Что делать, если..., если вам скучно с помощью интро)
Этот вопрос не относится к VBScript в частности (я просто использовал его в этом случае): я хочу найти решение для использования общих регулярных выражений (включая редакторы).
Это началось, когда я хотел создать адаптацию Пример 4, где 3 группы захвата используются для разделения данных по 3 ячейкам в MS Excel. Мне нужно было захватить одну общую картину, а затем, внутри нее, захватить еще 3 шаблона. Тем не менее, в том же выражении мне также нужно было захватить еще один вид рисунка и снова захватить еще 3 паттерна внутри него (да, я знаю... но прежде чем указывать пальцем нудиус, пожалуйста, закончите чтение).
Я думал сначала о Named Capturing Groups, тогда я понял, что не должен "смешивать названные и пронумерованные группы захвата", так как это "не рекомендуется, потому что ароматы несовместимы в том, как нумеруются группы".
Затем я просмотрел VBAcript SubMatches и "не захватывающий" Groups, и я получил рабочее решение для конкретного случая:
For Each C In Myrange
strPattern = "(?:^([0-9]+);([0-9]+);([0-9]+)$|^.*:([0-9]+)\s.*:([0-9]+).*:([a-zA-Z0-9]+)$)"
If strPattern <> "" Then
strInput = C.Value
With regEx
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = strPattern
End With
Set rgxMatches = regEx.Execute(strInput)
For Each mtx In rgxMatches
If mtx.SubMatches(0) <> "" Then
C.Offset(0, 1) = mtx.SubMatches(0)
C.Offset(0, 2) = mtx.SubMatches(1)
C.Offset(0, 3) = mtx.SubMatches(2)
ElseIf mtx.SubMatches(3) <> "" Then
C.Offset(0, 1) = mtx.SubMatches(3)
C.Offset(0, 2) = mtx.SubMatches(4)
C.Offset(0, 3) = mtx.SubMatches(5)
Else
C.Offset(0, 1) = "(Not matched)"
End If
Next
End If
Next
Вот демо в Rubular регулярного выражения. В них:
124; 12; 3
мой id1: 213 мой id2: 232 мое слово: ins4yanrgx
: 8587459: 18254182540215: dcpt
0; 1; 2
Он возвращает первые 2 ячейки с числами и 3 rd с числом или словом. В основном я использовал группу без захвата с двумя "родительскими" паттернами ( "родители" = широкие шаблоны, где я хочу обнаружить другие подматрицы). Если родительский шаблон 1 st имеет соответствующий поднабор (1 st), тогда я помещаю его значение и оставшиеся захваченные группы этого шаблона в 3 ячейки. Если нет, я проверяю, была ли сопоставлена группа захвата 4 th (принадлежащая родительскому шаблону 2 nd) и поместить остальные подматрицы в те же 3 ячейки.
Что делать, если...
Вместо того, чтобы иметь что-то вроде этого:
(?:^(\d+);(\d+);(\d+)$|^.*:(\d+)\s.*:(\d+).*:(\w+)$|what(ever))
Возможно, что-то подобное:
(#:^(\d+);(\d+);(\d+)$)|(#:^.*:(\d+)\s.*:(\d+).*:(\w+)$)|(#:what(ever))
Где (#:
вместо создания группы, не содержащей захвата, создаст "родительскую" нумерованную группу захвата.
Таким образом, я мог бы сделать что-то похожее на Пример 4:
C.Offset(0, 1) = regEx.Replace(strInput, "#$1")
C.Offset(0, 2) = regEx.Replace(strInput, "#$2")
C.Offset(0, 3) = regEx.Replace(strInput, "#$3")
Он будет искать родительские шаблоны, пока не найдет совпадение в дочернем шаблоне (первое совпадение будет возвращено и, в идеале, не будет искать остальные).
Есть ли что-то вроде этого? Или я что-то скрываю от регулярного выражения, которое позволяет это сделать?
Другие возможные варианты:
- обратитесь к родительскому и дочернему шаблонам напрямую, например:
#2$3
(это было бы эквивалентно$6
в моем примере); - создайте столько групп захвата, сколько необходимо в других (я думаю, это было бы более сложным, но также и самой интересной частью), например: с регулярным выражением (такой же синтаксис), как
(#:^_(?:(#:(\d+):\w+-(\d))|(#:\w+:(\d+)-(\d+)))_$)|(#:^\w+:\s+(#:(\w+);\d-(\d+))$)
и выборка##$1
в шаблонах, таких как:_123:smt-4_
он будет соответствовать: 123_ott:432-10_
он будет соответствовать: 432yant: special;3-45235
он будет соответствовать: специальному
Скажите, пожалуйста, если вы заметили какие-либо ошибки или недостатки в этой логике, я отредактирую как можно скорее.