Войти

Показать полную графическую версию : массив из строк, поиск по строке


matson
08-06-2017, 16:55
Добрый день.
Пытаюсь решить задачу по парсингу лог-файла с конца самого файла. Получилось поделить лог на строки и строки положить в одномерный массив. Вот только как произвести поиск по строке, которая лежит внутри ячейки одномерного массива?

На примере:

вот такой вариант работает (ищет точку входа в строку):
z = " 2017-06-07 23:01 Пользователь sadfasdasd qwddsda dqwd sad qwdsad asd"
y = InStr(1, z, "Пользователь")

а вот такой нет (всегда 0):

z = my_arr(10) ' в данной ячейке лежит строка " 2017-06-07 23:01 Пользователь sadfasdasd qwddsda dqwd sad qwdsad asd"
y = InStr(1, z, "Пользователь")

nexochyka
08-06-2017, 18:15
Проверь формат ячейки (as string ?). У меня твой пример работает.
y=InStr(1, my_arr(10), "польз", vbTextCompare)

Iska
08-06-2017, 18:40
с конца самого файла. »
и:
положить в одномерный массив »
входят в явное противоречие. Используйте базу данных.

внутри ячейки одномерного массива? »
У массивов нет ячеек. Есть элементы.

а вот такой нет (всегда 0): »
Чушь.

Упакуйте образец лог-файла в архив и приложите к сообщению. Опишите задачу.

matson
09-06-2017, 11:03
задача: есть лог от Cobian Backup, необходимо получить данные о успешном/не успешном резервном копировании и количестве ошибок (если есть). Задание может выполняться несколько раз за сутки, следовательно необходима самая последняя запись в txt (поэтому читаем лог снизу вверх). По завершении задачи будет запускаться данный скрипт (средствами Cobian).
нет никакого смысла использовать бд для такой простой задачи, не люблю плодить сущности.
Для вашего "чушь" гифка по ссылке как это работает (точнее как не работает)GIF (https://media.giphy.com/media/xUA7b61tNrZMtdM1by/giphy.gif)
msgbox (TypeName(my_arr(9))) говорит что лежит строка


Кусок лога имеет такой вид

2017-06-07 18:10 --
2017-06-07 21:00 *** Запущено новое копирование. Заданий в очереди: 1 ***
2017-06-07 21:00 Отключение возможности входа в спящий режим...
2017-06-07 21:00 ** Выполнение задания "BackGTD" **
2017-06-07 21:00 Подсчёт файлов в задании "BackGTD"...
2017-06-07 21:00 Запуск теневого копирования тома: D:\
2017-06-07 21:01 Теневая копия создана
2017-06-07 21:01 Соединение с "192.168.3.8:21"...
2017-06-07 21:01 TLS недоступен на указанном сервере, попытка обычного соединения...
2017-06-07 21:01 Пользователь "administrator" начал сеанс связи с "192.168.3.8:21"
2017-06-07 21:01 Каталог "BackGTD 2017-06-07 21;01;07 (Разностный)" создан
2017-06-07 21:01 Каталог cменён на "BackGTD 2017-06-07 21;01;07 (Разностный)"
2017-06-07 21:01 Закачка каталога "GLOBALROOT\Device\HarddiskVolumeShadowCopy11\BackGTD"
2017-06-07 21:44 Удаление теневой копии "587861c8-ae9a-494f-b00d-428cd458c070"
2017-06-07 21:44 Теневая копия удалена
2017-06-07 21:44 Общее время выполнения задания "BackGTD": 0 ч., 44 мин., 11 сек.
2017-06-07 21:44 ** Задание "BackGTD" завершено. Ошибок: 0, обработано файлов: 45789, скопировано файлов: 5131, общий размер: 25,91 GB **
2017-06-07 21:44 --
2017-06-07 21:44 Возможность входа в спящий режим включена
2017-06-07 21:44 Общее время копирования: 0 ч., 44 мин., 15 сек.
2017-06-07 21:44 *** Копирование завершено. Ошибок: 0, обработано файлов: 45789, скопировано файлов: 5131, общий размер: 25,91 GB ***
2017-06-07 21:44 --


вот таким скриптом получаю строки. В 9 элементе массива лежит строка "2017-06-07 23:01 Пользователь....". На количество переменных не обращайте внимания,

Dim F, i, s, fn, FSO, ForReading, AllTxt, listLines, str, x, arr_Line, my_arr(), y, z, nStrok, SearchString
ForReading = 1
fn = "C:\Users\root\Desktop\log 2017-06-07.txt" '// <-- full path
arr_Line = 0
Set FSO = CreateObject("Scripting.FileSystemObject")
Set F = FSO.OpenTextFile(fn, ForReading, False, -2)
Do Until F.AtEndOfStream ' пока наступит конец файла
Redim Preserve my_arr(arr_Line)
my_arr(arr_Line) = F.ReadLine ' Считываем строку
arr_Line = arr_Line + 1
nStrok = UBound(my_arr)
Loop
F.Close

msgbox my_arr(9)
'z = "2017-06-07 23:01 Пользователь sadfasdasd qwddsda dqwd sad qwdsad asd"
y = InStr(1, my_arr(9), "Польз", vbTextCompare)
msgbox y

greg zakharov
09-06-2017, 11:27
По логу (ровно как и по самой постановке задачи) ничего не понятно: нужно извлекать данные из лога по какому критерию? На какие значения нужно опираться? Зачем каждую строку пихать в массив, чай ведь не экономный расход ресурсов?

matson
09-06-2017, 11:39
Смотрите: в логах ищем строку "Задание "BackGTD" завершено. Ошибок:". При нахождении подстроки в элементе массива (InStr >0) начинаем работать со строкой и получать дату-время, количество ошибок и т.п., а это отправляется на zabbix.
Зачем каждую строку пихать в массив, чай ведь не экономный расход ресурсов? »
Если вы подскажете более правильный и красивый вариант, я буду очень признателен. Не нашел пока более правильного варианта поиска данных в строке, если строк с одинаковым текстом может быть несколько (то есть несколько одинаковых строк "Задание "BackGTD" завершено. Ошибок:", только разное количество ошибок)

greg zakharov
09-06-2017, 11:51
Есть такая штука, RegExp называется. Открываете файл на чтение, читаете построчно, и если строкка соответствует шаблону регулярного выражения, извлекаете данные из подгрупп регулярки (дату, количество ошибок, обработанных файлов и дыр и пыр).

matson
09-06-2017, 13:35
Толи лыжи не едут...
пытаюсь сделать проверку на чтении построчно
Dim F, i, s, fn, FSO, ForReading, AllTxt, listLines, str, x, arr_Line, my_arr(), y, z, nStrok, SearchString
ForReading = 1
fn = "C:\Users\root\Desktop\log 2017-06-07.txt" '// <-- full path
arr_Line = 0
Set FSO = CreateObject("Scripting.FileSystemObject")
Set F = FSO.OpenTextFile(fn, ForReading, False, -2)
SearchString = "Теневая копия создана"

Do Until F.AtEndOfStream ' пока наступит конец файла
Str = F.ReadLine
If (InStr(1, Str, SearchString) > 0) Then
MsgBox Str
End If
Loop
F.Close

Но тишина! Хотя строчка, содержащая "Теневая копия создана" точно присутствует в файле

matson
09-06-2017, 15:13
дело было не в бобине, дело было в кодировке...

Iska
09-06-2017, 19:47
дело было не в бобине, дело было в кодировке... »
Вот потому и предлагалось:
Упакуйте образец лог-файла в архив и приложите к сообщению. »
а не копировать «кусок лога» в виде текста.

megaloman
09-06-2017, 19:55
matson, Не понимаю, что Вы хотите в конце концов получить, но вот вариант (тестировал на файле, созданном на основе приведенного Вами текста):File_In = "Z:\Box_In\Логфайл.log"
Find_String = "** Задание ""BackGTD"" завершено."

Set FSO = CreateObject("Scripting.FileSystemObject")

Set NFile = FSO.OpenTextFile(File_In, 1, False) ' Открываем текстовый файл
S = NFile.ReadAll
NFile.Close

MsgBox Last_String(S, Find_String)

Function Last_String(All_S, Find_S)
i_Find_S = InStrRev(All_S, Find_S)
If i_Find_S > 0 Then
NFind_1 = InStrRev(All_S, vbCrLf, i_Find_S)
NFind_2 = InStr(i_Find_S, All_S, vbCrLf)
Last_String = LTrim(RTrim(Replace(Mid(All_S, NFind_1, NFind_2 - NFind_1 + 1), vbCrLf, "")))
Else
Last_String = ""
End If
End FunctionНе вижу смысла получать массив.

Iska
09-06-2017, 21:35
нет никакого смысла использовать бд для такой простой задачи, не люблю плодить сущности. »
Пока лог в сотни килобайт — да, возможно. Когда в сотни мегабайт — тогда стоит работать с ним либо как с базой данных, либо задействовать LogParser.




© OSzone.net 2001-2012