Что нового

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,671
Репутация
2,481
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,671
Репутация
2,481
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,671
Репутация
2,481
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
Репутация
626
Suppir
Предупреждение
1. Используй тэги AutoIt
autoit.gif
для выделения кода в тексте
2. Выделяй цитаты тэгами для цитаты
quote.gif
, либо выдели желаемый текст для цитирования и нажми появившуюся ссылку для вставки цитаты в окно для сообщения. Для этого нужно в профиле убрать WYSIWYG режим редактирования сообщений и разрешить быстрый ответ на странице
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
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,671
Репутация
2,481
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).
 
Верх