我当前正在搜索包含IP地址的日志文件。
日志示例:
10.1.177.198 Tue Jun 19 09:25:16 CDT 2018
10.1.160.198 Tue Jun 19 09:25:38 CDT 2018
10.1.177.198 Tue Jun 19 09:25:36 CDT 2018
10.1.160.198 Tue Jun 19 09:25:40 CDT 2018
10.1.177.198 Tue Jun 19 09:26:38 CDT 2018
10.1.177.198 Tue Jun 19 09:27:16 CDT 2018
10.1.177.198 Tue Jun 19 09:28:38 CDT 2018
我目前可以从日志的最后一行获取IP地址。我还可以搜索具有相同IP地址的所有行号。
如果日志中的最后一个IP地址在日志中列出了3次或多次,我如何获得该IP地址倒数第三次出现的行号?
例如,我要获取此行的行号:
10.1.177.198 Tue Jun 19 09:26:38 CDT 2018
或者更好的是,只需打印整行。
这是我的代码示例:
import re
def run():
try:
logfile = open('read.log', 'r')
for line in logfile:
x1 = line.split()[0]
for num, line in enumerate(logfile, 0):
if x1 in line:
print("Found " + x1 + " at line:", num)
print ('Last Line: ' + x1)
logfile.close
except OSError as e:
print (e)
run()
我列出了特定IP地址所在的所有行号。
print("Found " + x1 + " at line:", num)
我要打印其中“ num”是行号列表中倒数第三的行。
我的总体目标是从日志文件的最后一行中获取IP地址。然后检查它以前是否已被列出3次以上。如果有的话,我想找到地址的倒数第3位并获取行号(或仅打印该行上列出的地址和日期)
答案 0 :(得分:1)
跟踪所有事件,并从最后一个开始打印第三个事件。可以使用heapq
进行优化。
def run():
try:
logfile = open('log.txt', 'r')
ip_address_line_number = dict()
for index,line in enumerate(logfile,1):
x1 = line.split()[0]
log_time = line.split()[4]
if x1 in ip_address_line_number :
ip_address_line_number[x1].append((index,log_time))
else:
ip_address_line_number[x1] = [(index,log_time)]
if x1 in ip_address_line_number and len(ip_address_line_number.get(x1,None)) > 2:
print('Last Line: '+ ip_address_line_number[x1][-3].__str__())
else:
print(x1 + ' has 0-2 occurences')
logfile.close
except OSError as e:
print (e)
run()
答案 1 :(得分:0)
另一种查看方式,如果文件是反向读取的 :
3+1
个观察到的第一个IP。有些many tools可以提供更简单的代码,但这是一种灵活的通用方法,旨在提高内存效率。大致来说,让我们:
3+1
个观察给出
文件test.log
# test.log
10.1.177.198 Tue Jun 19 09:25:16 CDT 2018
10.1.160.198 Tue Jun 19 09:25:38 CDT 2018
10.1.177.198 Tue Jun 19 09:25:36 CDT 2018
10.1.160.198 Tue Jun 19 09:25:40 CDT 2018
10.1.177.198 Tue Jun 19 09:26:38 CDT 2018
10.1.177.198 Tue Jun 19 09:27:16 CDT 2018
10.1.177.198 Tue Jun 19 09:28:38 CDT 2018
和reverse_readline()
generator的代码,我们可以编写以下代码:
代码
def run(filename, target=3, min_=3):
"""Return the line number and data of the `target`-last observation.
Parameters
----------
filename : str or Path
Filepath or name to file.
target : int
Number of final expected observations from the bottom,
e.g. "third to last observation."
min_ : int
Total observations must exceed this number.
"""
idx, prior, data = 0, "", []
for i, line in enumerate(reverse_readline(filename)):
ip, text = line.strip().split(maxsplit=1)
if i == 0:
target_ip = ip
if target == 0:
idx, *data = prior
if ip == target_ip:
target -= 1
prior = i, ip, text
# Edge case
total_obs = prior[0]
if total_obs < min_:
print(f"Minimum observations was not met. Got {total_obs} observations.")
return None
# Compute line number
line_num = (i - idx) + 1 # add 1 (zero-indexed)
return [line_num] + data
演示
run("test.log")
# [5, '10.1.177.198', 'Tue Jun 19 09:26:38 CDT 2018']
第二次观察:
run("test.log", 2)
# [6, '10.1.177.198', 'Tue Jun 19 09:27:16 CDT 2018']
所需的最少观察值:
run("test.log", 2, 7)
# Minimum observations was not met. Got 6 observations.
根据需要添加错误处理。
详细信息
注意:“观察”是包含目标ip的行。
reverse_readline()
生成器。target_ip
是从反转文件的“第一”行确定的。prior
(减少内存消耗)。target
是一个计数器,每次观察后都会递减。当target
计数器达到0
时,将保存prior
观测值,直到发生器耗尽为止。 prior
是一个元组,其中包含用于最后观察目标ip地址(即索引,地址和文本)的行数据。total_obs
长度和文件长度,该文件用于计算line_num
ber。答案 2 :(得分:0)
使用pandas
会很短:
import pandas as pd
df = pd.read_fwf('read.log', colspecs=[(None, 12), (13, None)], header=None, names=['IP', 'time'])
lastIP = df.IP[df.index[-1]]
lastIP_idx = df.groupby('IP').groups[lastIP]
n = 3
if len(lastIP_idx) >= n:
print('\t'.join(list( df.loc[lastIP_idx[-n]] )))
else:
print('occurence number of ' + lastIP + ' < ' + str(n))