Извлечение значений времени из списка и добавление в новый список или массив - PullRequest
1 голос
/ 31 января 2020

У меня есть скрипт, который читает файл журнала, который содержит сотни этих журналов, и ищет те, которые имеют тип «Вкл., Выкл. Или Переключение». Затем я вывожу каждый журнал в свой список. Я пытаюсь найти способ извлечь время выхода и время в отдельный список / массив, а затем вычесть два раза, чтобы найти продолжительность каждого отдельного журнала. Вот как выглядят выходные журналы:

['2020-01-31T12:04:57.976Z 1234 Out: [2020-01-31T00:30:20.150Z] Id: {"Id":"4-f-4-9-6a"', '"Type":"Switch"', '"In":"2020-01-31T00:30:20.140Z"']

Это мой текущий код:

logfile = '/path/to/my/logfile'

with open(logfile, 'r') as f:
    text = f.read()
    words = ["On", "Off", "Switch"]
    text2 = text.split('\n')
    for l in text.split('\n'):
        if (words[0] in l or words[1] in l or words[2] in l):
            log = l.split(',')[0:3]

Я застрял на том, как настроить таргетинг только на значения времени Out и In из логи и положить их в массив и преобразовать в значение времени, чтобы найти продолжительность.

Первоначальный журнал перед сценарием: все, что находится после времени ввода, бесполезно для того, что я ищу, поэтому у меня выводятся только первые три индекса

2020-01-31T12:04:57.976Z 1234 Out: [2020-01-31T00:30:20.150Z] Id: {"Id":"4-f-4-9-6a","Type":"Switch,"In":"2020-01-31T00:30:20.140Z","Path":"interface","message":"interface changed status from unknown to normal","severity":"INFORMATIONAL","display":true,"json_map":"{\"severity\":null,\"eventId\":\"65e-64d9-45-ab62-8ef98ac5e60d\",\"componentPath\":\"interface_css\",\"displayToGui\":false,\"originalState\":\"unknown\",\"closed\":false,\"eventType\":\"InterfaceStateChange\",\"time\":\"2019-04-18T07:04:32.747Z\",\"json_map\":null,\"message\":\"interface_css changed status from unknown to normal\",\"newState\":\"normal\",\"info\":\"Event created with current status\"}","closed":false,"info":"Event created with current status","originalState":"unknown","newState":"normal"}

Ответы [ 2 ]

1 голос
/ 31 января 2020

Ниже приведено возможное решение. Строка wordmatch - это что-то вроде хака, пока я не нахожу что-то более понятное: это всего лишь одна строка, которая создает пустой набор или набор из 1 элемента True, если одно из слов совпадает. (Не проверено)

import re

logfile = '/path/to/my/logfile'

words = ["On", "Off", "Switch"]
dateformat = r'\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d+[Zz]?'
pattern = fr'Out:\s*\[(?P<out>{dateformat})\].*In":\s*\"(?P<in>{dateformat})\"'
regex = re.compile(pattern)
with open(logfile, 'r') as f:
    for line in f:
        wordmatch = set(filter(None, (word in s for word in words)))
        if wordmatch:
            match = regex.search(line)
            if match:
                intime = match.group('in')
                outtime = match.group('out')
                # whatever to store these strings, e.g., append to list or insert in a dict.

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

Я также не включил (если это необходимо) преобразование в datetime.datetime объект. Для этого прочтите документацию модуля datetime, в частности datetime.strptime. (В качестве альтернативы вы можете сохранить результаты в таблице Pandas. В этом случае прочтите документацию Pandas о том, как преобразовать строки в фактические объекты даты и времени.)

Вы также не Вам нужно прочитать nad split в новых строках самостоятельно: for line in f сделает это за вас (при условии, что f действительно является файловым дескриптором).

0 голосов
/ 01 февраля 2020

Regex - это, вероятно, путь к go (быстрота, эффективность и т. Д. c.) ... но ...

Вы можете использовать очень упрощенный c (если очень неэффективный) подход очистки ваших данных:

  • объедините все это в строку
  • замените вещи, которые мешают простому анализу
  • , разделите разумно и отфильтруйте разделение

примерно так:

data = ['2020-01-31T12:04:57.976Z 1234 Out: [2020-01-31T00:30:20.150Z] Id: {"Id":"4-f-4-9-6a"', '"Type":"Switch"', '"In":"2020-01-31T00:30:20.140Z"']

all_text = " ".join(data)


# this is inefficient and will create throwaway intermediate strings - if you are
# in a hurry or operate on 100s of MB of data, this is NOT the way to go, unless
# you have time

# iterate pairs of ("bad thing", "what to replace it with") (or list of bad things)
for thing in [ (": ",":"), (list('[]{}"'),"") ]:
    whatt = thing[0]
    withh = thing[1]

    # if list, do so for each bad thing
    if isinstance(whatt, list):
        for p in whatt:
            # replace it
            all_text = all_text.replace(p,withh)
    else:
        all_text = all_text.replace(whatt,withh)

# format is now far better suited to splitting/filtering
cleaned = [a for a in all_text.split(" ") 
           if any(a.startswith(prefix) or "Switch" in a 
                  for prefix in {"In:","Switch:","Out:"})]

print(cleaned)

Выходы:

['Out:2020-01-31T00:30:20.150Z', 'Type:Switch', 'In:2020-01-31T00:30:20.140Z']

После очистки ваши данные будут выглядеть так:

2020-01-31T12:04:57.976Z 1234 Out:2020-01-31T00:30:20.150Z Id:Id:4-f-4-9-6a Type:Switch In:2020-01-31T00:30:20.140Z

Вы можете преобразовать чистый список в словарь для простоты поиска:

d = dict( part.split(":",1) for part in cleaned)

print(d)

будет выдавать:

{'In': '2020-01-31T00:30:20.140Z', 
 'Type': 'Switch', 
 'Out': '2020-01-31T00:30:20.150Z'}

Вы можете использовать модуль datetime для анализа времени из ваших значений, как показано в 0 0 пост.

...