5 回答
TA贡献1840条经验 获得超5个赞
以下代码片段将生成一个字典列表,日志文件中的每一行都有一个字典。
import re
def parse_log(log_file):
regex = re.compile(r'^([0-9\.]+) - (.*) \[(.*)\] (".*")')
def _extract_field(match_object, tag, index, result):
if match_object[index]:
result[tag] = match_object[index]
result = []
with open(log_file) as fh:
for line in fh:
match = re.search(regex, line)
if match:
fields = {}
_extract_field(match, 'host' , 1, fields)
_extract_field(match, 'user_name', 2, fields)
_extract_field(match, 'time' , 3, fields)
_extract_field(match, 'request' , 4, fields)
result.append(fields)
return result
def main():
result = parse_log('log.txt')
for line in result:
print(line)
if __name__ == '__main__':
main()
TA贡献1772条经验 获得超8个赞
我现在正在做这门课程,我得到的答案是
import re
def logs():
with open("assets/logdata.txt", "r") as file:
logdata = file.read()
# YOUR CODE HERE
pattern='''
(?P<host>[\w.]*)
(\ -\ )
(?P<user_name>([a-z\-]*[\d]*))
(\ \[)
(?P<time>\w.*?)
(\]\ \")
(?P<request>\w.*)
(\")
'''
lst=[]
for item in re.finditer(pattern,logdata,re.VERBOSE):
lst.append(item.groupdict())
print(lst)
return lst
TA贡献1826条经验 获得超6个赞
使用str.split()andstr.index()也可以工作,忽略正则表达式的需要。此外,您可以直接迭代文件处理程序,这会逐行生成一行,因此您不必将整个文件加载到内存中:
result = []
with open('logdata.txt') as f:
for line in f:
# Isolate host and user_name, discarding the dash in between
host, _, user_name, remaining = line.split(maxsplit=3)
# Find the end of the datetime and isolate it
end_bracket = remaining.index(']')
time_ = remaining[1:end_bracket]
# Slice out the time from the request and strip the ending newline
request = remaining[end_bracket + 1:].strip()
# Create the dictionary
result.append({
'host': host,
'user_name': user_name,
'time': time_,
'request': request
})
from pprint import pprint
pprint(result)
TA贡献1865条经验 获得超7个赞
一旦您解决了您遇到的正则表达式问题 - 下面的代码将适合您
import re
result = []
with open('data.txt') as f:
lines = [l.strip() for l in f.readlines()]
for logdata in lines:
host = (re.findall('(.*?)\-',logdata))
username = re.findall('\-(.*?)\[',logdata)
_time = re.findall('\[(.*?)\]', logdata)
request = re.findall('\"(.*?)\"',logdata)
result.append({'host':host,'user_name':username,'time':_time,
'request':request})
print(result)
TA贡献1797条经验 获得超6个赞
assets/logdata.txt下面的函数返回一个字典列表,其中包含根据您的原始问题每行匹配的所需键/值。
值得注意的是,应在此基础上实施适当的错误处理,因为存在明显的边缘情况可能会导致代码执行意外停止。
请注意您的模式的变化host,这很重要。示例中使用的原始模式不仅仅匹配host每行的部分,在模式开头添加锚点会re.MULTILINE停止匹配误报,这些误报将与原始示例中的每行的其余部分匹配。
import re
def logs():
with open("assets/logdata.txt", "r") as file:
logdata = file.read()
host = (re.findall('^(.*?)\-',logdata, re.MULTILINE))
username = re.findall('\-(.*?)\[',logdata)
time = re.findall('\[(.*?)\]', logdata)
request = re.findall('\"(.*?)\"',logdata)
return [{ "host": host[i].strip(), "username": username[i], "time": time[i], "request": request[i] } for i,h in enumerate(host)]
以上是基于您原始帖子的简单/最小解决方案。有很多更干净、更有效的方法可以解决这个问题,但是我认为从您现有的代码开始工作,让您了解如何纠正它是相关的,而不仅仅是为您提供一个更好的优化解决方案,相对而言,对你来说意义不大。
添加回答
举报