1

Тема: VBScript: работа с "обрамляющими" конструкциями в рег. выражениях

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

Set objRegExp = CreateObject("VBScript.RegExp")
objRegExp.Global = True
Str = "<t1>a<t2>b<t3>"
objRegExp.Pattern = "<[\s\S]*>"
Set objMatches = objRegExp.Execute(Str)
For Each objMatch In objMatches
    WScript.Echo objMatch.Value
Next

В данном примере конструкция [\s\S]* означает "любое количество любых символов".
Однако, результат может показаться немного неожиданным: возвращены будут вовсе не три фрагмента <t1>, <t2> и <t3> по отдельности, вся строка целиком как один фрагмент. Происходит это потому, что вся строка целиком, как ни странно, вполне удовлетворяет шаблону <[\s\S]*>. Такое поведение регулярных выражений называется "жадным", когда подходящим считается наиболее длинный фрагмент, удовлетворяющий шаблону. Чтобы сделать регулярное выражение "нежадным", в нашем шаблоне следует использовать знак вопроса после звёздочки:

<[\s\S]*?>

В этом случае три фрагмента <t1>, <t2> и <t3> будут возвращены по отдельности.

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

2

Re: VBScript: работа с "обрамляющими" конструкциями в рег. выражениях

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

Например: необходимо извлечь все фрагменты, начинающиеся на "a" и заканчивающиеся на "b", и находящиеся только внутри угловых скобок. Скажем, из строки:

<123a1b123>a2b<a11b>a22b<a111b>

Нужно извлечь a1b, a11b, a111b, которые находятся внутри угловых скобок, но никак не a2b и a22b, которые находятся вне угловых скобок. Проблема решается следующим образом:

Set objRegExp = CreateObject("VBScript.RegExp")
objRegExp.Global = True
Str = "<123a1b123>a2b<a11b>a22b<a111b>"
objRegExp.Pattern = "(<[\s\S]*?)(a[\s\S]*?b)([\s\S]*?>)"
Set objMatches = objRegExp.Execute(Str)
For Each objMatch In objMatches
    WScript.Echo objMatch.SubMatches(1)
Next

В данном случае шаблон (<[\s\S]*?)(a[\s\S]*?b)([\s\S]*?>) состоит из трёх частей, ограниченных скобками, которые будут возвращены в коллекции SubMatches каждого найденного совпадения (соответственно, с индексами 0, 1 и 2). Первая часть означает "открывающая угловая скобка, затем любое количество любых символов". Вторая часть означает "буква а, затем любое количество любых символов, затем буква b". Третья часть означает "любое количество любых символов, затем закрывающая угловая скобка". При получении нам нужна только вторая часть (с индексом 1), и именно её мы и получаем.

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

3

Re: VBScript: работа с "обрамляющими" конструкциями в рег. выражениях

Теперь задача, похожая на предыдущую, но "наоборот": необходимо извлечь все фрагменты, начинающиеся на "a" и заканчивающиеся на "b", и находящиеся только вне угловых скобок. Решение:

Set objRegExp = CreateObject("VBScript.RegExp")
objRegExp.Global = True
Str = "<123a1b123>a2b<a11b>a22b<a111b>"
objRegExp.Pattern = "(^|>)[^<]*?(a[^<>]*?b)[^>]*?(<|$)"
Set objMatches = objRegExp.Execute(Str)
For Each objMatch In objMatches
    WScript.Echo objMatch.SubMatches(1)
Next

"Вне конструкции" - это значит, что непосредственно слева - либо ничего, либо только закрывающая угловая скобка, а справа - либо ничего, либо только открывающая угловая скобка, т.е. шаблон такой: "начало строки ИЛИ закрывающая - любые символы кроме открывающей - наш шаблон - любые символы кроме закрывающей - открывающая ИЛИ конец строки".

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