Автор Тема: StringRegExp, можно ли использовать заранее определенную переменную в шаблоне?  (Прочитано 7431 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Suppir [?]

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

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


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


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

но тогда теряется гибкость (особенно в случае альтернативных шаблонов и использовании элементов массива) и придется огромное количество кода набивать вручную
« Последнее редактирование: Ноябрь 10, 2009, 11:49:47 от Kaster »

Русское сообщество AutoIt


Оффлайн SyDr [?]

  • Локальный модератор
  • *
  • Сообщений: 649
  • Репутация: 157
  • Пол: Мужской
  • Сидра
    • Награды
  • Версия AutoIt: 3.3.12.0
Возможно. Просто ты используешь $date не как переменную, а как строку.

Код: AutoIt [Выделить]
StringRegExp($Line, "^Дата создания " & $date)


Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7827
  • Репутация: 2288
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Suppir [?]
Цитировать
переменная $date внутри скобок интерпретируется как литерал
За это поведение отвечает опция Opt("ExpandVarStrings", 1) (см. в справке).


Правила, Поиск, Супер тема


AutoIt is simple, subtle, elegant.


«Не оказываю тех. поддержку через ПМ/ICQ, и по электронной почте - для этого есть форум. (C)»
«Законы Мэрфи неоспоримы!»


Мои работы

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
Спасибо, у меня возник следующий вопрос по теме.

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


Далее я ищу с помощью регулярных выражений:
Код: AutoIt [Выделить]
$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].

Отсюда вопрос: как достать совпадение, найденное с помощью заранее определенной переменной?
« Последнее редактирование: Ноябрь 10, 2009, 11:50:36 от Kaster »

Русское сообщество AutoIt


Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7827
  • Репутация: 2288
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Suppir [?]
Цитировать
В Perl можно все в одну строчку записать
И тут тоже :)

Код: AutoIt [Выделить]
#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)


Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
Повторю нерешенный вопрос:

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


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

Код: AutoIt [Выделить]
$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].

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




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

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


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

Всем спасибо.
« Последнее редактирование: Ноябрь 10, 2009, 11:51:54 от Kaster »

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7827
  • Репутация: 2288
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Suppir [?]
Цитировать
т.е. в массиве $Matches нет элемента $Matches[1].
Массив начинается с [0], и в этом случае содержит первый элемент именно там (ну или вовсе нет совпадений, нужно проверять уровень ошибочности).

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


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


Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
Цитата: Creator
А так разве не проще:
$Matches = StringRegExp($Line, "^(.+)\s(" & $Initiales & ")", 1)

Не знал, что так можно. Имхо, немножко тяжеловесно получается, тем более, что в тексте, который нужно разобрать, очень много скобок и кавычек (кавычек особенно...).

Цитата: Creator
или так (для надёжности, ведь не всегда инициалы будут во втором совпадений?):

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

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

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

Русское сообщество AutoIt


Оффлайн Kaster [?]

  • Бритва, Бритва Оккама
  • Глобальный модератор
  • *
  • Сообщений: 4020
  • Репутация: 622
  • Пол: Мужской
  • Мой Аватар, он лучший самый
    • Награды
  • Версия AutoIt: 3.3.14.0
Suppir
Предупреждение1. Используй тэги AutoIt для выделения кода в тексте
2. Выделяй цитаты тэгами для цитаты , либо выдели желаемый текст для цитирования и нажми появившуюся ссылку для вставки цитаты в окно для сообщения. Для этого нужно в профиле убрать WYSIWYG режим редактирования сообщений и разрешить быстрый ответ на странице
« Последнее редактирование: Ноябрь 10, 2009, 11:57:18 от Kaster »
Конференция посвященная AutoIt на jabber.ru - [email protected]
Как попасть на конференцию читаем тут


Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7827
  • Репутация: 2288
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Suppir [?]
Цитировать
мне нужно поймать строки вида:
"Заместитель управления А.А. Иванов" и построить хеш-таблицу "должность - фамилия". Поэтому обе скобки необходимы.
Тогда можно так:
Код: AutoIt [Выделить]
$Line = "Заместитель управления А.А. Иванов"
$Initiales = "[А-Я]\.\s*[А-Я]\.\s*[А-Я][а-я]+"
$Match = StringRegExpReplace($Line, "^(.+)\s(" & $Initiales & ")$", "$1 - $2")
MsgBox(0, "", $Match)


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

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

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

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

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
CreatoR  [?]
Цитировать
Вообще в регулярных выражений есть оператор Or (|)...

Дело в том, что в регулярных выражениях Perl использование конструкции альтернации "|" в шаблонах, содержащих метасимволы и квантификаторы, замедляет обработку регулярного выражения на порядок. Эту удивительную (и не очень приятную особенность) я заметил не так давно:

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

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


Добавлено: Ноябрь 10, 2009, 14:32:14
CreatoR  [?]
Цитировать
Такая функция уже намечается для следующих версий, а пока есть _StringRegExpReplaceEx, которая поддерживает вызов Callback-функций для обработки результата.

Спасибо за информацию! Очень интересно.
Вообще, я новичок в AutoIt, но язык мне очень понравился - настолько все просто и элегантно сделано, что диву даешься :)

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7827
  • Репутация: 2288
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
Suppir [?]
Цитировать
в регулярных выражениях Perl использование конструкции альтернации "|" в шаблонах, содержащих метасимволы и квантификаторы, замедляет обработку регулярного выражения на порядок
В AutoIt тоже, но тут нет поддержки пакетов, а только дополнительный вызов функций. Чтобы в AutoIt написать оптимальный код (для ускорения подобных обработок данных), нужно немного(?) поломать голову :), ну и опыт конечно сильно помогает.

Впрочем вот как можно сделать что то типа передачи пакетов (кривая аналогия ;D ):
Код: AutoIt [Выделить]
$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).

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
CreatoR  [?]
Цитировать
можно сделать что то типа передачи пакетов

Понятно. Буду разбирался с функциями _StringRegExpEx и StringFormat.

Русское сообщество AutoIt


 

Похожие темы

  Тема / Автор Ответов Последний ответ
1 Ответов
2788 Просмотров
Последний ответ Февраль 01, 2010, 12:57:59
от madmasles
22 Ответов
7871 Просмотров
Последний ответ Сентябрь 26, 2011, 23:28:43
от incrome
7 Ответов
3056 Просмотров
Последний ответ Сентябрь 28, 2011, 21:36:30
от jilexandr
10 Ответов
3401 Просмотров
Последний ответ Июнь 03, 2012, 15:38:30
от CreatoR
2 Ответов
2214 Просмотров
Последний ответ Май 08, 2013, 09:22:28
от AZJIO
2 Ответов
1123 Просмотров
Последний ответ Ноябрь 02, 2015, 11:16:47
от ra4o
2 Ответов
1487 Просмотров
Последний ответ Декабрь 12, 2015, 17:55:09
от alex33
3 Ответов
774 Просмотров
Последний ответ Декабрь 09, 2016, 01:09:52
от Garrett
3 Ответов
1479 Просмотров
Последний ответ Сентябрь 20, 2017, 14:27:30
от InnI
1 Ответов
441 Просмотров
Последний ответ Октябрь 09, 2017, 23:59:13
от Garrett