Это небольшое руководство по разгадке тайн загадочного StringRegExp().
StringRegExp( "test", "pattern" [, flag ] )
"test" = Строка, в которой выполняется поиск совпадений.
"pattern" = Строка (шаблон), состоящая из определенных ключевых символов (метасимволов), которые позволяют ТОЧНО узнать, что необходимо получить. Но это не аналог ключевых слов And, Or, Not, а это либо совпадение, либо не совпадение.
flag [необязательный] = Указывает функции, хотите ли вы узнать найдено совпадение по шаблону или нет, или вы хотите получить первое совпадение с шаблоном, или вы хотите получить все совпадения с шаблоном в тексте "test".
Пример 1
MsgBox(0, "SRE, пример 1", StringRegExp("text", 'test'))
В этом примере, окно сообщения выдаст "0", это означает, что шаблон
"test" не был найден в тестовой строке "text". Я знаю, что это слишком просто, но теперь вы знаете почему он не был найден.
Следующий способ задать шаблон - использование диапазона/набора символов ("[ ... ]"). Это можно сравнить к логической функцией "ИЛИ". Давайте используем предыдущий пример. Предположим нам необходимо найти строку "test" или "text". Итак, я начинаю искать шаблон, рассуждая подобно функции SRE: первый символ совпадения - "t", далее буква "e", это одинаково для обоих строк, которые мы ищем. Теперь необходимо найти "s" или "x", поэтому можно использовать набор в качестве подмены: "[sx]" означающий соответствию "s" или "x". Далее последняя буква "t".
Пример 2
MsgBox(0, "SRE, пример 2", StringRegExp("text", 'te[sx]t'))
MsgBox(0, "SRE, пример 2", StringRegExp("test", 'te[sx]t'))
Оба окна сообщения должны выдать "1", потому что шаблон соответствует обоим строкам "test" и "text".
Вы также можете указать количество повторов символа используя "{число повторов}" или вы можете указать диапазон, используя "{min, max}". Первый пример ниже содержит излишние указания повторов, но показывает что имеется в виду:
Пример 3
MsgBox(0, "SRE, пример 3", StringRegExp("text", 't{1}e{1}[sx]{1}t{1}'))
MsgBox(0, "SRE, пример 3", StringRegExp("aaaabbbbcccc", 'b{4}'))
$asResult = StringRegExp("Это тестовый пример", '(тест)', 1)
If @error == 0 Then
MsgBox(0, "SRE, пример 4", $asResult[0])
EndIf
$asResult = StringRegExp("Это тестовый пример", '(те)(ст)', 1)
If @error == 0 Then
MsgBox(0, "SRE, пример 4", $asResult[0] & "," & $asResult[1])
EndIf
Итак, первый шаблон должен соответствовать какому-нибудь месту текстовой строки. Если это так, то SRE сообщит о "захвате" любой группы ("()") и поместит их в возвращаемый массив. Вы можете использовать множественный захват, о чем свидетельствует вторая часть кода в примере 4.
Ладно, вернемся к лог-файлу. Теперь, когда мы знаем, как "захватывать" текст, давайте составим наш шаблон: Поскольку мы уже определились, что нужно искать число, известно 3 способа указать "соответствие любой цифре": "[:digit:]", "[0-9]", и "\d". Первый наверно самый лёгкий для понимания. Есть несколько классов (digit, alnum, space, и т.д. Смотрите в этой справке полный список) вы можете использовать определённый набор символов, одним из которых является набор цифр. Обычный диапазон можно задать с помощью "[0-9]", что означает все цифры от 0 до 9. Метасимвол "\d" означает тоже, что первые два. Между этими 3-мя способами нет различия и со всеми SRE существуют несколько способов создать любой шаблон.
Итак, первоначально нам из известно, что необходимо захватить цифры, поэтому указываем это открытием скобки "(". Далее, нам известно, что количество символов от 1 до 3 и все состоят из цифр, поэтому наш шаблон теперь выглядит так: "([0-9]{1,3}". И, наконец, закрываем его закрывающей скобкой, обозначающий конец группы: "([0-9]{1,3})". Давайте попробуем:
Пример 5
$asResult = StringRegExp("Были 18 листов оставшихся в пачке бумаги.", '([0-9]{1,3})', 1)
If @error == 0 Then
MsgBox(0, "SRE, пример 5", $asResult[0])
EndIf
В примере вы увидите, диалоговое окно корректно отображающее число "18".
Далее необходимо предотвратить захват группы. Для этого открываем группу таким способом: "(?:" вместо обычного "(". Допустим, что ваш log-файл сообщает "Вы использовали 36 из 279 страниц." Теперь, если вы запустите пример 5, то вы найдёте "36" вместо "279". Теперь то, что я люблю делать - определить разницу между числами. Одно число - то, которое выскакивает в диалоговом окне, второе число всегда содержит последующий пробел и слово "страниц". Можно было бы изменить предыдущий шаблон "([0-9]{1,3} страниц)", но что если наш скрипт должен просто отображать начальное количество страниц, без присоединение текста " страниц" в конец числа? Здесь вы можете использовать группы без захвата, чтобы решить эту задачу.
Пример 6
$asResult = StringRegExp("Вы использовали 36 из 279 страниц.", '([0-9]{1,3})(?: страниц)', 1)
If @error == 0 Then
MsgBox(0, "SRE, пример 6", $asResult[0])
EndIf
Это можно продолжать бесконечно, но в основном хотелось выложить основу работы регулярных выражений, и то как "думает" SRE. Имейте ввиду:
- Не забывайте воспринимать части шаблона как за один символ
- Функция StringRegExp() ищет первый символ указанный в шаблоне, далее уже ваша задача - предоставить достаточно подтверждений, чтобы "доказать" является это или не является точным совпадением. Пример 6 наглядно показывает это.
- Помните, набор [ ... ] означает ИЛИ ([xyz] соответствует одному из символов "x" ИЛИ "y", ИЛИ "z")
Если у вас есть какие-либо вопросы, обратитесь сначала к файлу справки! Он подробно объясняет синтаксис, который поставляется вместе с SRE. Обращайте внимание на группу "повторителей символов". Это может сделать ваш шаблон более читабельным заменяя определенные символы для диапазонов. Например: "*" эквивалентно {0,} или диапазону от 0 до любого количества символов.
Удачи. Регулярные выражения могут значительно уменьшить длину вашего кода, и сделать его легко понятным для последующего изменения. Исправления и отзывы приветствуются!
Учебник регулярных выражений за 30 минут - от Jim Hollenhorst.
GUI для тестирования различных шаблонов StringRegExp() -
Спасибо steve8tch. Credit: w0uter
Благодарность neogia за этот урок.