Что нового

Поиск совпадающего фрагмента в 2х текстовых файлах

mef-t

Осваивающий
Сообщения
306
Репутация
30
Добрый день.

Есть лог объемом в 500 записей. 1 запись лога представляет собой одну строчку текста.
Новая запись лога сдвигает весь лог вниз на 1 строчку, при этом на первое место встает новая запись, а последняя запись удаляется.
Периоды появления новой записи могут быть разными, от 10 строк в 10 секунд, до 1 записи в 3 часа.
Необходимо получить историю лога с учетом затираемых записей.
К сожалению время записи лога я так и не смог получить, по этому у меня встала необходимость написать скрипт, который будет объединять выгрузки лога в один общий файл, удаляя повторявшиеся записи.

Прошу помочь подобрать логику и оптимальный алгоритм объединения выгрузок лога (по 500 записей) в один файл.
Как я это вижу

Есть исходный файл с 500 или более строками.
Есть второй файл с 500 строками.
Необходимо найти участок текста в обоих файлах, который бы совпадал.
При этом в исходном файле данный участок должен начинаться с 1 символа текста.
Во втором файле данный участок должен оканчиваться последним символом текста.
Участок текста должен включать в себя строки целиком. При этом количество строк на искомом участке не известно.

Для примера первый текст:
Код:
123
12
234
12
432
123
534
213
453
123
342

Второй текст:
Код:
123
1234
12
345
123
67854
234
567
234
123
12
234
12
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
mef-t
время записи лога я так и не смог получить
Вы хотите сказать, что в строке отсутствует время её записи? Или в строке есть время? И, в целом, насколько строки уникальны?

А какой из этих текстов является историей, а какой логом? И где у них совпадающая часть (идущие подряд одинаковые строки)?
 
Автор
mef-t

mef-t

Осваивающий
Сообщения
306
Репутация
30
Garrett, спасибо. тема интересная. Изучу и после отпишусь.
Upd. Не подходит. Данная UDF позволяет отследить изменения в папке. А мне могли бы помочь изменения в файле, а не в папке.


----------------------------
InnI сказал(а):
Вы хотите сказать, что в строке отсутствует время её записи? Или в строке есть время? И, в целом, насколько строки уникальны?
Я выдираю лог из приложения(даты вытащить не смог). Поэтому в текущей задаче дат нет совсем.

А какой из этих текстов является историей, а какой логом? И где у них совпадающая часть (идущие подряд одинаковые строки)?
Первый - исходный.
В первый файл нужно добавить строки второго файла без учета совпадающего участка.

Совпадающий участок
Код:
123
12
234
12

Т.е. первый (исходный) текст после преображения должен выглядеть так:
Код:
123
1234
12
345
123
67854
234
567
234
123
12
234
12
432
123
534
213
453
123
342


Самый простой способ, это брать 2 (или 3) последних строчки второго текста и искать их в первом тексте.
Если нашли, то брать с первой строчки по найденную в первом тексте и сравнивать с таким же количеством строк во втором тексте.
Если не нашли, то выходим.
Если сошло, то запоминаем этот текст.
Затем берем на одну строчку больше чем найдено и сверяем с тем же количеством строк в другом файле.
И так повторяем.
В итоге, когда по всем пунктам не находим сходства, выходим, а результатом будет сохраненный текст.

Но это метод перебора. Возможно есть более простой.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
mef-t
Но это метод перебора. Возможно есть более простой.
Перебор и есть самый простой :smile:
Как вариант, можно использовать StringInStr(). Берёте весь лог и "ищете" его во всей истории. Если не совпало, удаляете верхнюю строку и оставшееся опять "ищете" в истории. Когда найдёте, будете знать сколько строк назад начали "поиск" и эти строки переносите в историю.

А если перебором, то можно так.
Читаем три-пять верхних строк истории (т.е. последних по времени). Берём первую и ищем её с начала лога. Когда нашли, смотрим следующую. Если следующая лога не совпадает со второй из истории, то ищем первую "историческую" дальше. Если первая совпала и вторая совпала - проверяем третью. При несовпадении третьей, начинаем заново - 1, 2, 3. И т.д. Чем больше идущих подряд строк проверяем, тем точнее результат (зависит от частоты повторяемости строк). Когда все строки совпали - берём от первой совпавшей до начала и переносим в историю.
 
Автор
mef-t

mef-t

Осваивающий
Сообщения
306
Репутация
30
первый вариант наверно удобнее, хотя 500 записей... Нужно просто попробовать.
Спасибо.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
mef-t
Даже если у вас строка в 1024 ANSI-символа, весь файл займёт пол мегабайта памяти. Другое дело - сколько строк истории вы собираетесь хранить.
А если использовать перебор, то для ускорения желательно будет читать файлы в массивы, которые ещё больше места займут.
 
Автор
mef-t

mef-t

Осваивающий
Сообщения
306
Репутация
30
нууу... я полагаю, что в исходном файле сразу можно лишнее обрезать и не мучаться, т.е. оставить первые 500 записей.

На обработку ушло "Time: 0.09907"

Код:
$text1 = FileRead("1.txt")
$text2 = FileRead("2.txt")
$textsearch = $text2

While True

	$indexText = StringInStr($text1, $textsearch, 1) ; Поиск текста в тексте
	If $indexText > 0 Then ExitLoop
	$index = StringInStr($textsearch, @crlf) ; Поиск переноса
	If $index = 0 Then ExitLoop
	$textsearch = StringTrimLeft($textsearch, $index+1)

WEnd

ConsoleWrite($textsearch & @CRLF)



Вариант, где берем только 500 строк из файла размером в 9МБ (На обработку ушло "Time: 0.3331")
Код:
$hFile = FileOpen("1.txt", 0)

Dim $text1 = ''
For $i = 1 To 500
    $text1 &= FileReadLine($hFile, $i) & @CRLF
Next
FileClose($hFile)
$text1 = StringTrimRight ($text1, 2)

$text2 = FileRead("2.txt")
$textsearch = $text2

While True

	$indexText = StringInStr($text1, $textsearch, 1) ; Поиск текста в тексте
	If $indexText > 0 Then ExitLoop
	$index = StringInStr($textsearch, @crlf) ; Поиск переноса
	If $index = 0 Then ExitLoop
	$textsearch = StringTrimLeft($textsearch, $index+1)

WEnd

ConsoleWrite($textsearch & @CRLF)
 
Верх