Python:使用正则表达式提取日期和时间

时间:2018-08-07 18:32:01

标签: python

问题陈述:

我仅需要在特定时间后才能从文件收集日志,该时间可以采用以下格式:“ 8月7日11:00:00.000”或“ 8月7日11:00:00”。这些日志位于其他txt文件中,格式为:

Aug  7 11:00:00 abc newsyslog[25714]: logfile turned over due to size>1024K
Aug  7 11:00:00.000  abc xyz lol

以此类推。

如何使用正则表达式提取此特定日期和时间,然后仅在指定时间后收集日志?除了正则表达式,还有其他更好的使用方法吗?

现在使用此:

import re

monthnames = "(?:Jan\w*|Feb\w*|Mar\w*|Apr\w*|May|Jun\w?|Jul\w?|Aug\w*|Sep\w*|Oct\w*|Nov(?:ember)?|Dec\w*)"

pattern1 = re.compile(r"(\d{1,4}[\/\\\-]+\d{1,2}[\/\\\-]+\d{2,4})")

pattern4 = re.compile(r"(?:[\d,. \-]*[,. \-])?%s(?:[\,\.\ \-]+[\d]+[stndrh]*)+[:\d]*[\ ]?(PM)?(AM)?([\ \-\+\d]{4,7}|[UTCESTGMT\ ]{2,4})*"%monthnames, re.I)

patterns = [pattern4, pattern1]

s='Aug 7 11:00:00.000'

for pattern in patterns:
    print re.findall(pattern,s)

但是它什么也不返回,一个空列表!

需要帮助!

P.S-我只能在python中使用传统库,因为这是Junos的自动化脚本

2 个答案:

答案 0 :(得分:1)

您绝对不需要正则表达式-在空白处进行简单拆分,并且收集前两个结果应该绰绰有余,即:

log_lines = ["Aug  7 11:00:00 abc newsyslog[25714]: logfile turned over due to size>1024K",
             "Aug  7 11:00:00.000  abc xyz lol"]  # we'll use a list as an example

for line in log_lines:
    date_string = " ".join(line.split(None, 3)[:-1])
    print(date_string)

# Aug 7 11:00:00
# Aug 7 11:00:00.000

现在,您可以使用datetime.datetime.strptime()将其解析为本地日期时间对象,但是可能会受到格式的限制(即%b仅是当前语言环境的缩写,而不是所有平台/版本都支持单位数字日期),因此,考虑到如此简单的结构,您可能需要在捕获的日期时间字符串进行解析之前重建它们,以最大程度地实现兼容性:

month_abbr = {"jan": 1, "feb": 2, "mar": 3, "apr": 4, "may": 5, "jun": 6,
              "jul": 7, "aug": 8, "sep": 9, "oct": 10, "nov": 11, "dec": 12}

def parse_date(log_line):
    mon, day, tim = line.split(None, 3)[:-1]
    date_string = "{:02} {:02} ".format(month_abbr[mon.lower()], int(day)) + tim
    try:
        return datetime.datetime.strptime(date_string, "%m %d %H:%M:%S.%f")
    except ValueError as e:
        return datetime.datetime.strptime(date_string, "%m %d %H:%M:%S")

log_lines = ["Aug  7 11:00:00 abc newsyslog[25714]: logfile turned over due to size>1024K",
             "Aug  7 11:00:00.000  abc xyz lol"]  # we'll use a list as an example

for line in log_lines:
    date_object = parse_date(line)
    print(date_object)

# 1900-08-07 11:00:00
# 1900-08-07 11:00:00

注意:您的日期时间对象将以1900作为年份,因为您的日志没有年份信息。第二个日期时间对象也包含其微秒数据,只是没有使用datetime.datetime对象的默认表示而打印出来。

现在,您可以将这些日期时间对象与其他日期时间对象进行比较,并过滤掉/打印/做任何符合条件的行,例如如果只想在之后 Aug 7之后创建日志:

log_lines = ["Aug  7 11:00:00 abc newsyslog[25714]: logfile turned over due to size>1024K",
             "Aug  7 11:00:00.000  abc xyz lol",
             "Aug  8 11:00:00 foo bar"]  # we'll use a list as an example

min_date = datetime.datetime(1900, 8, 8)  # minimum date set to Aug 8

for line in log_lines:
    if parse_date(line) >= min_date:
        print(line)

# Aug  8 11:00:00 foo bar

答案 1 :(得分:1)

我认为正则表达式是一个过大的功能,我会提取日期部分,例如:

' '.join(line.split()[0:3])

然后将strptime()与较长的格式一起使用,捕获异常,并为较短的格式尝试使用strptime:

from datetime import datetime

def get_date(date_str):
    try:
        return datetime.strptime(date_str, '%b %d %H:%M:%S.%f')
    except ValueError:
        return datetime.strptime(date_str, '%b %d %H:%M:%S')