Что нового

StringRegExp, можно ли использовать заранее определенную переменную в шаблоне?

Suppir

Продвинутый
Сообщения
967
Репутация
62
Возможно ли использовать заранее определенную переменную в паттерне для функции StringRegExp?

Например, у меня есть переменная $date="12 октября 2009"
Я хочу написать:
Код:
if StringRegExp($Line, "^Дата создания $date") Then MsgBox()


Но переменная $date внутри скобок интерпретируется как литерал (ищет не "12 октября 2009" а последовательность "$date"). Возможно ли в AutoIt использовать переменные/элементы массива внутри паттернов поиска? Спасибо


***
про то, что паттерн можно заранее инициализировать с переменной я знаю:
Код:
$pattern = "^Дата создания " & $date
if StringRegExp($Line, $pattern) Then MsgBox()

но тогда теряется гибкость (особенно в случае альтернативных шаблонов и использовании элементов массива) и придется огромное количество кода набивать вручную
 

SyDr

Сидра
Сообщения
651
Репутация
158
Возможно. Просто ты используешь $date не как переменную, а как строку.

Код:
StringRegExp($Line, "^Дата создания " & $date)
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 175
Репутация
2 331
Suppir [?]
переменная $date внутри скобок интерпретируется как литерал
За это поведение отвечает опция Opt("ExpandVarStrings", 1) (см. в справке).
 
Автор
S

Suppir

Продвинутый
Сообщения
967
Репутация
62
Спасибо, у меня возник следующий вопрос по теме.

Например, у меня предопределена переменная
Код:
$Initiales="[А-Я]\.\s*[А-Я]\.\s*[А-Я][а-я]+";(ищет инициалы вроде "А.А. Иванов")


Далее я ищу с помощью регулярных выражений:
Код:
$Matches = StringRegExp($Line, "^(.+)\s" & $Initiales, 1)


Как теперь получить значение текста, найденного с помощью $Initiales?
По идее, в паттерне $Initiales нужно взять в скобку и он сохранится в $Matches[1]

НО если взять $Initiales в скобку, отладчик выдает:
"Array variable has incorrect number of subscripts or subscript dimension range exceeded.:"
т.е. в массиве $Matches нет элемента $Matches[1].

Отсюда вопрос: как достать совпадение, найденное с помощью заранее определенной переменной?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 175
Репутация
2 331
Suppir [?]
В Perl можно все в одну строчку записать
И тут тоже :smile:

Код:
#include "Date.au3"

$Line = "09.11.2009"
$sPattern = "(\d+)\.(\d+)\.(\d+)"
$Matches = StringRegExpReplace($Line, $sPattern, "$1" & _DateToMonth(StringRegExpReplace($Line, $sPattern, "$2")) & "$3")

ConsoleWrite($Matches & @CRLF)
 
Автор
S

Suppir

Продвинутый
Сообщения
967
Репутация
62
Повторю нерешенный вопрос:

Например, у меня предопределена переменная
Код:
$Initiales="[А-Я]\.\s*[А-Я]\.\s*[А-Я][а-я]+";(ищет инициалы вроде "А.А. Иванов")


Далее я ищу с помощью регулярных выражений:

Код:
$Matches = StringRegExp($Line, "^(.+)\s" & $Initiales, 1)


Как теперь получить значение текста, найденного с помощью $Initiales?
По идее, переменную $Initiales нужно взять в скобку и тогда текст, найденный с помощью $Initiales сохранится в $Matches[1]

НО если взять $Initiales в скобку, отладчик выдает:
"Array variable has incorrect number of subscripts or subscript dimension range exceeded.:"
т.е. в массиве $Matches нет элемента $Matches[1].

Отсюда вопрос: как достать совпадение, найденное с помощью заранее определенной переменной?




Все, спасибо, я разобрался. Делаем так:

Код:
Opt("ExpandVarStrings", 1)
$Initiales="[А-Я]\.\s*[А-Я]\.\s*[А-Я][а-я]+"
$Matches = StringRegExp($Line, "^(.+)\s($Initiales)", 1) 
MsgBox(0, "", $Matches[1])


напечатает именно то, что было найдено с помощью $Initiales

Всем спасибо.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 175
Репутация
2 331
Suppir [?]
т.е. в массиве $Matches нет элемента $Matches[1].
Массив начинается с [0], и в этом случае содержит первый элемент именно там (ну или вовсе нет совпадений, нужно проверять уровень ошибочности).

А так разве не проще:
Код:
$Line = "test А.А. Иванов test"
$Initiales="[А-Я]\.\s*[А-Я]\.\s*[А-Я][а-я]+"
$Matches = StringRegExp($Line, "^(.+)\s(" & $Initiales & ")", 1) 
MsgBox(0, "", $Matches[1])


или так (для надёжности, ведь не всегда инициалы будут во втором совпадений?):
Код:
$Line = "test А.А. Иванов test"
$Initiales = "[А-Я]\.\s*[А-Я]\.\s*[А-Я][а-я]+"
$Match = StringRegExpReplace($Line, "^.+\s(" & $Initiales & ").*", "\1")
MsgBox(0, "", $Match)
 
Автор
S

Suppir

Продвинутый
Сообщения
967
Репутация
62
Creator сказал(а):
А так разве не проще:
$Matches = StringRegExp($Line, "^(.+)\s(" & $Initiales & ")", 1)
Не знал, что так можно. Имхо, немножко тяжеловесно получается, тем более, что в тексте, который нужно разобрать, очень много скобок и кавычек (кавычек особенно...).

Creator сказал(а):
или так (для надёжности, ведь не всегда инициалы будут во втором совпадений?):
Я понял вашу идею. Собственно, мне нужно поймать строки вида:
"Заместитель управления А.А. Иванов" и построить хеш-таблицу "должность - фамилия". Поэтому обе скобки необходимы.

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

Код:
if (/\d\s+\d/ && !// && !/\d[,-:\.]\d/ && !/-го/ && /\d+,\s+\d+,/){print "В ряде цифр пропущена запятая"}
Здесь пять регулярных выражений, из которых три отрицательные. Если для каждого регулярного выражения писать StringRegExp($Line..., то очень длинный код получается. Может быть написать что-то вроде функции, которой можно несколько регулярных выражений передавать; и функция будет их применять последовательно на одну строку.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Suppir
Предупреждение
1. Используй тэги AutoIt
для выделения кода в тексте
2. Выделяй цитаты тэгами для цитаты
, либо выдели желаемый текст для цитирования и нажми появившуюся ссылку для вставки цитаты в окно для сообщения. Для этого нужно в профиле убрать WYSIWYG режим редактирования сообщений и разрешить быстрый ответ на странице
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 175
Репутация
2 331
Suppir [?]
мне нужно поймать строки вида:
"Заместитель управления А.А. Иванов" и построить хеш-таблицу "должность - фамилия". Поэтому обе скобки необходимы.
Тогда можно так:
Код:
$Line = "Заместитель управления А.А. Иванов"
$Initiales = "[А-Я]\.\s*[А-Я]\.\s*[А-Я][а-я]+"
$Match = StringRegExpReplace($Line, "^(.+)\s(" & $Initiales & ")$", "$1 - $2")
MsgBox(0, "", $Match)


Здесь пять регулярных выражений, из которых три отрицательные. Если для каждого регулярного выражения писать StringRegExp($Line..., то очень длинный код получается
Вообще в регулярных выражений есть оператор Or (|)...

Код:
If StringRegExp($Line, "\d\s+\d||\d[,-:\.]\d|-го|\d+,\s+\d+,") Then ConsoleWrite("В ряде цифр пропущена запятая")

хотя это не всегда сработает как нужно, очень часто зависит от последовательности шаблонов.

Может быть написать что-то вроде функции, которой можно несколько регулярных выражений передавать; и функция будет их применять последовательно на одну строку.
Такая функция уже намечается для следующих версий, а пока есть _StringRegExpReplaceEx, которая поддерживает вызов Callback-функций для обработки результата.
 
Автор
S

Suppir

Продвинутый
Сообщения
967
Репутация
62
CreatoR [?]
Вообще в регулярных выражений есть оператор Or (|)...
Дело в том, что в регулярных выражениях Perl использование конструкции альтернации "|" в шаблонах, содержащих метасимволы и квантификаторы, замедляет обработку регулярного выражения на порядок. Эту удивительную (и не очень приятную особенность) я заметил не так давно:

http://forum.vingrad.ru/act-Print/client/html/f-5/t-271216.html

После того, как переписал регулярные выражения в пакеты, быстродействие некоторых моих скриптов увеличилась в несколько раз! Скорее всего, в AutoIt будет подобная ситуация, так как используется аналогичный движок рег. выражений - PCRE.


Добавлено:
Сообщение автоматически объединено:

CreatoR [?]
Такая функция уже намечается для следующих версий, а пока есть _StringRegExpReplaceEx, которая поддерживает вызов Callback-функций для обработки результата.
Спасибо за информацию! Очень интересно.
Вообще, я новичок в AutoIt, но язык мне очень понравился - настолько все просто и элегантно сделано, что диву даешься :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 175
Репутация
2 331
Suppir [?]
в регулярных выражениях Perl использование конструкции альтернации "|" в шаблонах, содержащих метасимволы и квантификаторы, замедляет обработку регулярного выражения на порядок
В AutoIt тоже, но тут нет поддержки пакетов, а только дополнительный вызов функций. Чтобы в AutoIt написать оптимальный код (для ускорения подобных обработок данных), нужно немного(?) поломать голову :smile:, ну и опыт конечно сильно помогает.

Впрочем вот как можно сделать что то типа передачи пакетов (кривая аналогия ;D ):
Код:
$iRet = _StringRegExpEx("My String Is Ring", "/(Test)/ && /(ing)/")

$sRet = StringFormat("Return: %i, Match: %i", $iRet, @extended)
ConsoleWrite($sRet & @CRLF) ;Выводит Return: 1, Match: 2 (2-ое совпадение -> 2-ой пакет, т.к Test не найден)

Func _StringRegExpEx($sTest, $sPattern_Packages)
	Local $aSplit = StringRegExp($sPattern_Packages, "/(.*?[^\\/])/(?:\s+?&&\s+?)?", 3)
	
	For $i = 0 To UBound($aSplit)-1
		If StringRegExp($sTest, $aSplit[$i]) Then Return SetExtended($i+1, 1)
	Next
	
	Return 0
EndFunc


настолько все просто и элегантно сделано, что диву даешься
Да, на счёт простоты это 100%, у AutoIt это не отнять 8).
 
Верх