Автор Redline


Урок 5. Другие RegExp в AutoIt


Регулярные выражения при работе с окнами и элементами управления в них


Рассмотрим возможность использования регулярных выражений при работе с окнами и их элементами управления (controls).

RegExp в заголовках и классах окон


При работе с функциями WinWait, WinActivate и т.п. для идентификации окон могут использоваться текст заголовка или его класс. Для более гибкого описания классов и заголовков можно воспользоваться встроенным в эти функции механизмом RegExp.
От таких RegExp не требуется большого функционала - они нужны только для идентификации конкретного окна и, следовательно, могут только проверять совпадает ли заголовок/класс с заданным шаблоном.
Формат записи RegExp в таких функциях:

WinActivate('[REGEXPCLASS:шаблон]')
WinActivate('[REGEXPTITLE:шаблон]')


Когда бывает нужно воспользоваться данной возможностью:

Сами шаблоны для таких функций очень просты, приведу только один - он делает активным окно одного из браузеров (Internet Explorer, Firefox или Opera), если запущено несколько браузеров одновременно, то активным станет тот, который идет первым в массиве WinList

WinActivate('[REGEXPCLASS:(?i)mozillaui|IEFrame|OpWindow]')


RegExp в классах управляющих элементах окон


При использовании функций ControlClick, ControlSend и т.п. вы также можете воспользоваться RegExp при описании класса управляющего элемента окна, только класса.
Формат записи:

ControlClick('Title', '', '[REGEXPCLASS:шаблон]')


Небольшой пример запускает калькулятор и вставляет текст в поле ввода (Edit):

Run('calc')
WinWaitActive('[REGEXPCLASS:(?i)calc]')
ControlSetText('[REGEXPCLASS:(?i)calc]', '', '[REGEXPCLASS:it]', 'здесь был AutoIt')



Использование RegExp через объекты


Эта тема скорее для общего развития, а не для повседневного использования, поэтому обзор будет поверхностным. Возможно она пригодится тем, кто привык к формату RegExp других языков программирования.
Здесь мы рассмотрим возможности объекта VBScript.RegExp при использовании его в AutoIt!
Данный объект позволяет проверять текст на совпадение его с шаблоном, производить замены в тексте и выводить совпавшие элементы текста. Синтаксис шаблонов ничем не отличается от тех, что мы рассмотрели раньше.
Существуют и ограничения:

Если вы попробуете использовать один из методов этого списка, то это вызовет ошибку и крах скрипта.
Общий вид составления выражения выглядит так:

$oRE = ObjCreate('VBScript.RegExp') ; создание объекта
$oRE.IgnoreCase = 1 ; флаг игнорирования регистра текста шаблоном
$oRE.Global = 1 ; поиск всех совпадений в тексте
$oRE.MultiLine = 1 ; режим многострокового текста для точки "."
$oRE.Pattern = 'pattern' ; сам шаблон


Проверка соответствия текста шаблону


Эту функцию выполняет метод Test, в зависимости от совпадения с шаблоном выводит True или False.
Пример проверяет строку чтобы она состояла только из символов английского алфавита:

$oRE = ObjCreate('VBScript.RegExp')
$oRE.IgnoreCase = 1
$oRE.Global = 1
$oRE.MultiLine = 0
$oRE.Pattern = '^[a-z]+$'
$sText = 'abcdefgh'
$sResult = $oRE.Test($sText)
ConsoleWrite($sResult & @CRLF)


Расшифровка шаблона:
"^" - начало строки
"[a-z]+" - любое количество символов из набора a-z, но хотя бы один
"$" - конец текста

Замена текста


Данную функцию выполняет метод Replace. Как и StringRegExpReplace, данный метод поддерживает обратные ссылки.
Пример производит разметку разрядов чисел, по три числа в разряде:

$oRE = ObjCreate('VBScript.RegExp')
$oRE.IgnoreCase = 1
$oRE.Global = 1
$oRE.MultiLine = 0
$oRE.Pattern = '(\d)(?=(\d{3})+(\D|$))'
$sText = '987 9876 98765 987 9876 9876543 98765432 987 9879'
$sResult = $oRE.Replace($sText, '$1.')
ConsoleWrite($sResult & @CRLF)


Расшифровка шаблона:
"(\d)" - группа с захватом, в которую входит один цифровой символ (соответствует обратной ссылке $1)
"(?=" - условие позитивного просмотра вперед, т.е. место перед...
"(\d{3})+" - ...любым количеством групп с захватом из трех цифровых символов, но хотя бы одной
"(\D|$)" - группа с захватом из символа отличного от цифры или конца текста
Т.е. данный шаблон найдет цифру, за которой идет еще минимум 3 цифры или любое количество цифр кратное трем, после которых стоит не цифра или конец текста. Replace заменит такую цифру на неё же и допишет точку за ней, после чего продолжит поиск.

Извлечение информации


Для извлечения информации используется метод Execute.
Обычный RegExp выводит массив, а метод Execute коллекцию.
В примере показаны два способа обращения с коллекцией, а также приведены свойства элементов коллекции. Сам пример выводит из текста только числа:

$oRE = ObjCreate('VBScript.RegExp')
$oRE.IgnoreCase = 1
$oRE.Global = 1
$oRE.MultiLine = 0
$oRE.Pattern = '\d+'
$sText = 'text 123 text 4321 text 123452'
$oMatches = $oRE.Execute($sText) ; коллекция $oMatches будет включать в себя все совпадения с шаблоном
$iCount = $oMatches.Count ; свойство Count соответствует количеству совпавших элементов
ConsoleWrite('Количество совпадений: ' & $iCount & @CRLF)
ConsoleWrite('Первый способ работы с коллекцией:' & @CRLF & '--------' & @CRLF)
For $oMatch In $oMatches ; стандартный перебор всех значений внутри коллекции
    ConsoleWrite('Значение совпавшего элемента: ' & $oMatch.Value & @CRLF) ; свойство Value содержит значение элемента коллекции $oMatch
    ConsoleWrite('Номер позиции во входящей строке: ' & $oMatch.FirstIndex & @CRLF) ; свойство FirstIndex содержит порядковый номер первого совпавшего символа данного элемента во входящей строке
    ConsoleWrite('Количество символов в элементе: ' & $oMatch.Length & @CRLF) ; свойство Length содержит количество символов в элементе
    ConsoleWrite('---' & @CRLF)
Next
ConsoleWrite('Второй способ работы с коллекцией:' & @CRLF & '--------' & @CRLF)
For $i = 0 To $iCount - 1 ; перебор значений коллекции по порядковому номеру
    $oMatch = $oMatches.Item($i) ; $oMatch - объект коллекции с соответствующим номером
    ConsoleWrite('Значение совпавшего элемента: ' & $oMatch.Value & @CRLF)
    ConsoleWrite('Номер позиции во входящей строке: ' & $oMatch.FirstIndex & @CRLF)
    ConsoleWrite('Количество символов в элементе: ' & $oMatch.Length & @CRLF)
    ConsoleWrite('---' & @CRLF)
Next


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

$oRE = ObjCreate('VBScript.RegExp')
$oRE.IgnoreCase = 1
$oRE.Global = 1
$oRE.MultiLine = 0
$oRE.Pattern = '\d+'
$sText = '<td>string15</td>  <div>string25</div>  <i>string36</i>'
$sPattern = '<[^>]+>(.*?)</[^>]+>'
$oRE.Pattern = $sPattern
$oMatches
= $oRE.Execute($sText)
$iCount = $oMatches.Count
ConsoleWrite('Количество совпадений: ' & $iCount & @CRLF)
ConsoleWrite('Первый способ работы с коллекцией:' & @CRLF & '--------' & @CRLF)
For $oMatch In $oMatches
    ConsoleWrite('Значение совпавшего элемента: ' & $oMatch.Value & @CRLF)
    $oSubMatches = $oMatch.SubMatches ; коллекция элементов, соответствующая группам с захватом
    ConsoleWrite('Количество совпадений с "группой с захватом": ' & $oSubMatches.Count & @CRLF)
    For $oSubMatch In $oSubMatches
        ConsoleWrite('Элемент, совпавший с "группой с захватом": ' & $oSubMatch & @CRLF)
    Next
    ConsoleWrite('---' & @CRLF)
Next
ConsoleWrite('Второй способ работы с коллекцией:' & @CRLF & '--------' & @CRLF)
For $i = 0 To $iCount - 1
    $oMatch = $oMatches.Item($i)
    ConsoleWrite('Значение совпавшего элемента: ' & $oMatch.Value & @CRLF)
    $oSubMatches = $oMatch.SubMatches
    $iSubCount = $oSubMatches.Count
    ConsoleWrite('Количество совпадений с "группой с захватом": ' & $iSubCount & @CRLF)
    For $j = 0 To $iSubCount - 1
        ConsoleWrite('Элемент, совпавший с "группой с захватом": ' & $oSubMatches.Item($j) & @CRLF)
    Next
    ConsoleWrite('---' & @CRLF)
Next