Нужно узнать позицию начала этого выражения в файле, чтобы сделать замену.
StringRegExpReplace
Дата;...;20.02.2015;21.02.2015;22.02.2015
Время;...;17:18;18:20;20:47
Ещё чего-то;...
Дата;23.02.2015
Время;...
Ещё чего-то;...
Как вариант, можно. Но,[list type=decimal]C2H5OH сказал(а):Нужно узнать позицию начала этого выражения в файле, чтобы сделать замену.
А почему сразу не сделать замену?
Код:StringRegExpReplace
Ksaan сказал(а):Вроде так должно работатьКод:$sChars = FileRead($hFile) Local $aRes = StringRegExp($sChars, '(Дата;[\d\.;]*?)\r\n(Время;[\d:;]*?)\r\n(Ещё чего-то;[\d\.;]*?)$', 1) $sResult = StringInStr($hFile, $aRes[0]) MsgBox(0, "позиция:", $sResult)
Local $hFile = FileOpen($sFile, 1)
FileSetPos($hFile, 0, 0)
$sFile = FileRead($hFile)
Local $aRes = StringRegExp($sFile, '(Дата;[\d\.;]*?)\r\n(Время;[\d:;]*?)\r\n(Ещё чего-то;[\d\.;]*?)$', 1)
FileSetPos($hFile, StringInStr($sFile, $aRes[0])-1, 0)
CreatoR сказал(а):Мне вот интересно как найти позицию найденного, если использовать флаг 3 (Return array of global matches)?
Конечно можно использовать 1 и прокручивать в цикле, но почему не предусмотрено тоже самое для глобального поиска...
Сам цикл выполняется быстро, пустой выполняет миллион операций за десятые доли секунды. Движок регулярных выражений оптимизировали, кэширует строку регулярного выражения, хотя этот критерий вроде не сильно помогает, ведь он сравнивает строку с предыдущей использованной строкой чтобы не компилировать регулярное выражение, конечно тут бы добавить функцию компиляции и тогда задача бы решилась навсегда. И добавилось что обработка данных функцией и нативный формат строк теперь одинаковый и поиск пошаговый вызывает меньше тормозов. То есть с момента появления новой версии AutoIt скорость режимов регулярный выражений нужно тестировать заново чтобы дать оценку.Разница в скорости циклов AutoIt и PCRE просто огромная
У меня в StringRegExp шаблон для поиска содержит 5 групп. Не думаю, что определение и суммирование длин каждой группы будет быстрее, чем StringInStr.AZJIO сказал(а):@extended - возвращает позицию конца. Выполните StringLen для найденного образца и отнимите это значение от @extended. Это должно работать быстрее чем StringInStr.
Я ж это и предлагал.Оно иногда надо, иногда не надо, более мягкий вариант добавление нового режима 5, 6 и т.д., чтобы не ломать существующие.
На скорость циклов AutoIt это не повлияло.Движок регулярных выражений оптимизировали, кэширует строку регулярного выражения ...
Было бы не полохо, но, по моим наблюдениям, скорость выполнения увеличится на величину порядка одного- двух процентов.тут бы добавить функцию компиляции и тогда задача бы решилась навсегда.
Не думаю, что определение и суммирование длин каждой группы будет быстрее, чем StringInStr.
$sChars = FileRead($hFile)
Local $aRes = StringRegExp($sChars, '(Дата;[\d\.;]*?)\r\n(Время;[\d:;]*?)\r\n(Ещё чего-то;[\d\.;]*?)$', 1)
If @error Then
MsgBox(0, "позиция:", "нет совпадений")
Else
$sResult = @extended
$sResult -= StringLen($aRes[0])
MsgBox(0, "позиция:", $sResult)
EndIf
Проверяем:C2H5OH сказал(а):Не думаю, что определение и суммирование длин каждой группы будет быстрее, чем StringInStr.
будет, imho.
Local $sText = FileRead($hFile)
Local $aRes = StringRegExp($sText, '(Дата;[\d\.;]*?)\r\n(Время;[\d:;]*?)\r\n(Ещё чего-то;[\d\.;]*?)$', 1)
ConsoleWrite(f1($aRes, @extended) & @CRLF)
ConsoleWrite(f2($sText, $aRes) & @CRLF)
ConsoleWrite('StringLen: ' & _Test1($aRes, @extended) & @CRLF)
ConsoleWrite('StringInStr: ' & _Test2($sText, $aRes) & @CRLF)
Func f1($aRes, $iEnd)
Local $sResult = $iEnd
For $i = 0 To UBound($aRes)-1
$sResult -= StringLen($aRes[$i])
Next
Return $sResult-4
EndFunc
Func f2($sText, $aRes)
Return StringInStr($sText, $aRes[0], 1, -1)
EndFunc
Func _Test1($aRes, $iEnd)
Local $t = TimerInit()
For $i = 1 To 100000
f1($aRes, $iEnd)
Next
Return TimerDiff($t)
EndFunc
Func _Test2($sText, $aRes)
Local $t = TimerInit()
For $i = 1 To 100000
f2($sText, $aRes)
Next
Return TimerDiff($t)
EndFunc
Func _Test(f, $v1, $v2)
Local $t = TimerInit()
For $i = 1 To 100000
f($v1, $v2)
Next
Return TimerDiff($t)
EndFunc
StringLen: 928.410656413941
StringInStr: 533.278990727546
Зависит от конкретных условий. Если обработка мегабайта данных то конечно процесс компиляции несоизмеримо мал к прочессу обрабатываемых данных. А если взять в цикле пару регулярных выражений, которые обновляют кэш и требуют перекомпиляции на каждом шаге, а размер обрабатываемой строки несколько десятков символов, например обработка имён файлов в цикле. И так что такое компиляция в моём представлении (наверно нужно Google сначала, но...): первоначальная обработка шаблона на ошибки, выявления групп, раскрытия метасимволов, например \d заменяется на числовые диапазоны входящих в группу цифр и т.д. чтобы потом просто проверить вхождение символа в этот диапазон. Это тоже как анализатор подсветки чтобы определить код или интерпретатор чтобы определить ключевые слова. И компиляция зависит от размера и количества групп. В любом случае проценты составляют величину обработки строки регулярного выражения к обрабатываемой строке. Если обрабатываемая строка мала, а шаблон сложный то процент уже будет не 1 и 2, а как бы не 50. Это гипотетические мысли вслух, конечно же всё познаётся в тесте.Было бы не полохо, но, по моим наблюдениям, скорость выполнения увеличится на величину порядка одного- двух процентов.
For $html In $html_array
$reg_exp = StringRegExp('...', 'a')
$data_a = $reg_exp[0]
Next
For $html In $html_array
$reg_exp = StringRegExp('...', 'b')
$data_b = $reg_exp[0]
Next
For $html In $html_array
$reg_exp = StringRegExp('...', 'c')
$data_c = $reg_exp[0]
Next
For $html In $html_array
$reg_exp = StringRegExp('...', 'd')
$data_d = $reg_exp[0]
Next
For $html In $html_array
$reg_exp = StringRegExp('...', 'e')
$data_e = $reg_exp[0]
Next
Затем, что вычитать надо сумму длин всех групп, а не только первой, а также сумму длин символов, не вошедших в группы.AZJIO сказал(а):Зачем вы StringLen делаете в цикле?
AZJIO сказал(а):Чисто логически: StringInStr просматривает файл (строку) от начала до конца
AZJIO сказал(а):Лучший вариант для StringLen; искомая строка размером несколько мегабайт, а найденный шаблон несколько байт. В этом случает StringInStr будет перебирать миллионы символов перед тем как найти нужное и хуже всего, если он окажется в конце строки
т.к. искомый фрагмент находится в конце строки: символ '$' в шаблоне.occurrence [необязательный] Номер искомого вхождения подстроки в строку. Используйте отрицательное значение параметра для поиска справа.
Если ищется потом позиция, то зачем в шаблоне группы? А без групп флаг 1 возвращает весь найденный текст в первый элемент массива. Если же необходимы группы использовать флаг 2, тоже самое только первый элемент массива весь найденный текст.отняв от @extended длину первой группы?
да не важно где в данном случае начало поиска. И уточнение не до конца строки а до найденного, а в случае не найденного до конца, но тут оно по условию найдено.В моём случае, StringInStr как раз ведёт поиск с конца строки
Компиляция это процесс анализа регулярного выражения зависящий от сложности, а в примере явно задан 1 символ (ни одного метасимвола даже), то процесс компиляции равен получению номера символа "а". Хотя по тестам на оф.сайте декларировали в полтора раза ускорение цикла (хотя при каких условиях).Я надеялся что, за счет компиляции такое решение с 5 циклами будет быстрее чем 1 цикл но с 5 регулярками. Но результаты теста показали, что выигрыш в скорости был в пределах погрешности.
Очень даже важно, если начинать поиск с той стороны, где заведомо есть искомый фрагмент.AZJIO сказал(а):да не важно где в данном случае начало поиска.
А это мысль. Спасибо за подсказку.AZJIO сказал(а):Если же необходимы группы использовать флаг 2, тоже самое только первый элемент массива весь найденный текст.
В отличие от интерпретированных регулярных выражений, скомпилированные регулярные выражения увеличивают время запуска, но позволяют выполнять отдельные методы поиска совпадения с шаблоном быстрее. В результате выгода по производительности от скомпилированных регулярных выражений увеличивается пропорционально числу вызовов методов регулярных выражений.
Что то число слишком большой 13 000 вызовов требуется, чтобы окупить компиляцию рег.выр.если требуется выполнить только 10 вызовов методов поиска совпадения, интерпретированное регулярное выражение дает более высокую производительность. Однако скомпилированное регулярное выражение обеспечивает более высокую производительность при большом числе вызовов (в данном случае 13 000).