Python 从列表中提取时间值并添加到新列表或数组

Python 从列表中提取时间值并添加到新列表或数组,python,python-2.7,Python,Python 2.7,我有一个脚本,可以读取包含数百个日志的日志文件,并查找具有“开、关或开关”类型的日志。然后我将每个日志输出到它自己的列表中。我试图找到一种方法,将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":"202

我有一个脚本,可以读取包含数百个日志的日志文件,并查找具有“开、关或开关”类型的日志。然后我将每个日志输出到它自己的列表中。我试图找到一种方法,将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"']
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-time值,并将它们放入一个数组中,然后转换为一个time值来查找持续时间

脚本之前的初始日志:“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"}

下面是一个可能的解决方案。
wordmatch
行有点像黑客,直到我发现更清楚的东西:如果其中一个单词匹配,它只是一行代码,创建一个空的或1个元素的
True
。 (未经测试)

重新导入
日志文件='/path/to/my/logfile'
单词=[“开”、“关”、“开关”]
dateformat=r'\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d+[Zz]?'
pattern=fr'Out:\s*\[(?P{dateformat})\].*In:“\s*\”(?P{dateformat})\”'
regex=re.compile(模式)
打开(日志文件“r”)作为f:
对于f中的行:
wordmatch=set(过滤器(无,(单词中的单词表示单词中的单词)))
如果单词匹配:
match=regex.search(行)
如果匹配:
intime=match.group('in')
outtime=match.group('out'))
#存储这些字符串的任何内容,例如,附加到列表或插入到dict中。
如前所述,您的日志示例非常笨拙,因此这适用于示例行,但可能不适用于每一行。请根据需要进行调整

我还没有包括(如果需要)到
datetime.datetime
对象的转换。为此,请通读
datetime
模块文档,特别是
datetime.strtime
。(或者,您可能希望将结果存储在Pandas表中。在这种情况下,请通读Pandas文档,了解如何将字符串转换为实际的datetime对象。)


您也不需要自己阅读换行符上的nad split:
for line in f
将为您完成此操作(前提是
f
确实是一个文件句柄)。

Regex可能是一条路要走(快速、高效等)……但是

您可以采取一种非常简单(如果效率非常低)的方法来清理数据:

  • 把它全部连接成一个字符串
  • 替换妨碍轻松解析的内容
  • 明智地拆分并过滤拆分
像这样:

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"']
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模块从您的值中解析时间,如post中所示。

这是一种非常不幸的日志格式,有时只有空格、其他部分、逗号空格。并且
Id:
后面的大括号甚至都没有关闭!示例准确吗?它似乎有许多不一致之处。这可能是一种常规的pression是最方便的选项,尽管它将取决于日志文件中的其他行是否具有相同的格式,甚至没有细微的差异;后者可能会使正则表达式变得相当复杂。请将日志文件的实际内容粘贴到此处,以便我们对日志文件有一个清晰的了解。@DYZ是的,该示例是准确的。日志将显示它self很长,我只需要查看前3个索引就可以得到我需要的信息