Ну все элементы данных должны попасть в свой массив. А метка говорит в какой именно.
Встретил метку - заполняй другой массив. Я же приложил шаблон работы. Вот пример кода, который рабоатет но хочется оптимизировать, там много строк еще.
Но есть пара вопросов по поводу функции:
1. Не пойму никак зачем двигать FileSetPos? Вроде же по кольцу получается ходим в цикле. Запомнили, считали, восставовили и никогда не выйдем.
2. Зачем Return $aSearchParams ведь мы работаем через ByRef
На мой взгляд так было бы быстрее, во всех отношениях
Код:
#include <Array.au3>$sMark="Marc-"$sStrg="Daten-"$sComplStrg=""For$nN=0To9$sComplStrg&=$sMark&$nN&@CRLFFor$nJ=0To5$sComplStrg&="Row-"&$nJ&" "&$sStrg&$nN&"/"&$nJ&$nN&"/"&$nJ&$nN&"/"&$nJ&@CRLFNextNextFileDelete(@ScriptDir&"\Test.txt")FileWrite(@ScriptDir&"\Test.txt",$sComplStrg)MsgBox(0,"String",$sComplStrg); START; STEP 1 =========================================================================================================$aArray=StringRegExp(FileRead(@ScriptDir&"\Test.txt"),"("&$sMark&"\d+)\R((?s).+?)(?="&$sMark&"\d+|\Z)",3)_ArrayDisplay($aArray,"Array 1D"); STEP 2 ======================$nUB=UBound($aArray)Dim$nT=0,$aArray2D[$nUB/2][2]For$nN=0To$nUB-1Step2$aArray2D[$nT][0]=$aArray[$nN]$aArray2D[$nT][1]=StringRegExp($aArray[$nN+1],"([^\v]+)",3)$nT+=1Next_ArrayDisplay($aArray2D,"Array 2D"); Show all ======================For$nN=0ToUBound($aArray2D)-1_ArrayDisplay($aArray2D[$nN][1],"Arr. "&$nN)Next
P.S.
Функция FileReadLine С точки зрения производительности, использовать эту функцию в цикле, увеличивая параметр line на 1 при в каждом шаге цикла - является плохой идеей. Это заставляет AutoIt перечитывать файл с самого начала до указанной строки.
Но есть пара вопросов по поводу функции:
1. Не пойму никак зачем двигать FileSetPos? Вроде же по кольцу получается ходим в цикле. Запомнили, считали, восставовили и никогда не выйдем.
2. Зачем Return $aSearchParams ведь мы работаем через ByRef
Можно также код упростить. Массив меток объявить глобально: Global $aTagNames = ["метка1", "метка2", "метка3"]
Тогда первая строка функции: Func _GetNextParams($hFile, ByRef $aSearchParams)
А запросы к функции будут такими:
По вопросам:
1. Попробуйте убрать FileSetPos и недосчитаетесь половины массивов. Вне функции, цикл нахождения меток, внутри, цикл нахождения "параметров", продолжающий внешний, который завершается дойдя до новой метки либо конца файла. А так как, в функции, найденная метка уже прочтена, при выходе из функции, в первом цикле она будет пропущена и мы потеряем целый массив. Бесконечного цикла не будет. Мы просто устанавливаем позицию на пропущенную метку.
2. Return можно убрать.
Весь код можно сделать и в одном цикле и через рекурсию, но читаться для вас это будет сложнее. А по сути, тоже самое.
Тут разные могут быть алгоритмы. Действительно ли вам необходимо читать файл построчно? Ведь распарсить его можно и быстрее, прочитав целиком. Если метки, у вас, строго определены как метка1...меткаN, то это другой код, он конечно же проще. Код может быть разным, многое зависит также от того, сами ли вы создаёте файл, либо читаете сторонний.
Да, быстрее, тем более, если в файле, метки строго определены базовым именем и номером. FlieRead действительно шустрее FlieReadLine.
Функция FileReadLine С точки зрения производительности, использовать эту функцию в цикле, увеличивая параметр line на 1 при в каждом шаге цикла - является плохой идеей. Это заставляет AutoIt перечитывать файл с самого начала до указанной строки.
$sFile='E:\Test.txt'$sText=FileRead($sFile)$sText=StringRegExpReplace($sText,'(?m)^(метка\d+)$','[$1]'); обрамляем метки в квадратные скобки и работаем с текстом как с ini файломMsgBox(4096,"Переменная $sText","$sText =>"&$sText&"<="); $sText=StringRegExpReplace($sText,'\A[\r\n]+|[\r\n]+\z|(\R)(\R+)','$1') ; если надо удаляем все лишние переносы строк$aR=StringRegExp($sText,'(?m)^\[(?:[^]\r\n]+)\][\r\n]+((?:[^[\r\n].*(?:[\r\n]+|$))*)',3); получаем содержимое всех секций в массив_ArrayDisplay($aR,"Массив $aR")For$i=0ToUBound($aR)-1$aR[$i]=StringSplit($aR[$i],@CRLF,1); содержимое каждой секции разбиваем в массив по @CRLFNext_ArrayDisplay($aR[0],"Массив $aR[0]")
Тогда зачем писать большой код, который к тому же ещё и медленный.
Не в упрек, но этот код совершенно не годится для больших файлов
Как его использовать если таких меток 50 или 100000 ?
Тогда зачем писать большой код, который к тому же ещё и медленный.
Не в упрек, но этот код совершенно не годится для больших файлов
Как его использовать если таких меток 50 или 100000 ?
Автор вопроса неоднократно указал на FileReadLine. А вопрос в спайке со словом "на-лету" побудил меня показать именно такой вариант. Дело тут не в зачем, а в насколько это действительно необходимо человеку. Во всяком случае в ветке даны решения обоих вариантов и выбор есть.
На счёт меток согласен. Решается одной строчкой.
Ну, а лично я бы действительно прочитал файл целиком и разобрал регуляркой.
Если же файл очень большой, при FileRead, он полностью загружается в память. При чтении файла построчно, в памяти выделяется буфер небольшого размера и файл будет считываться блоками. Из блока читается строка и возвращается в переменную. Поэтому, не будет большой загрузки оперативной памяти. Таким образом, используя FileRead мы берём скоростью, но расплачиваемся памятью. В FileReadLine наоборот.
Спасибо за советы, это все я для себя делаю, гигнаских объемов не планируется, поэтому и тормоза наверное меня не будут беспокоить. Для меня важно сейчас понять и отладить работу, а с регулярными выражениями у меня не никак складывается. Захочу обновить и зависну. Я даже сейчас не понимаю, что там происходит и что мне надо под себя подгонять.