【问题标题】:Python script not iterating through arrayPython脚本没有遍​​历数组
【发布时间】:2015-03-03 23:15:36
【问题描述】:

所以,我最近开始学习 python,在工作中我们想要一些方法来简化在我们的日志文件中查找特定关键字的过程,以便更容易地告诉哪些 IP 将添加到我们的阻止列表中。

我决定编写一个 python 脚本,它会接收一个日志文件,接收一个包含关键术语列表的文件,然后在日志文件中查找这些关键术语,然后编写与会话匹配的行找到该关键术语的 ID;到一个新文件。

import sys
import time
import linecache
from datetime import datetime

def timeStamped(fname, fmt='%Y-%m-%d-%H-%M-%S_{fname}'):
    return datetime.now().strftime(fmt).format(fname=fname)

importFile = open('rawLog.txt', 'r') #pulling in log file
importFile2 = open('keyWords.txt', 'r') #pulling in keywords
exportFile = open(timeStamped('ParsedLog.txt'), 'w') #writing the parsed log

FILE = importFile.readlines()
keyFILE = importFile2.readlines()

logLine = 1  #for debugging purposes when testing
parseString = '' 
holderString = ''
sessionID = []
keyWords= []
j = 0

for line in keyFILE: #go through each line in the keyFile 
        keyWords = line.split(',') #add each word to the array

print(keyWords)#for debugging purposes when testing, this DOES give all the correct results


for line in FILE:
        if keyWords[j] in line:
                parseString = line[29:35] #pulling in session ID
                sessionID.append(parseString) #saving session IDs to a list
        elif importFile == '' and j < len(keyWords):  #if importFile is at end of file and we are not at the end of the array
                importFile.seek(0) #goes back to the start of the file
                j+=1        #advance the keyWords array

        logLine +=1 #for debugging purposes when testing
importFile2.close()              
print(sessionID) #for debugging purposes when testing



importFile.seek(0) #goes back to the start of the file


i = 0
for line in FILE:
        if sessionID[i] in line[29:35]: #checking if the sessionID matches (doing it this way since I ran into issues where some sessionIDs matched parts of the log file that were not sessionIDs
                holderString = line #pulling the line of log file
                exportFile.write(holderString)#writing the log file line to a new text file
                print(holderString) #for debugging purposes when testing
                if i < len(sessionID):
                    i+=1

importFile.close()
exportFile.close()

它没有遍历我的关键字列表,我可能犯了一些愚蠢的新手错误,但我没有足够的经验来意识到我搞砸了什么。当我检查输出时,它只在 rawLog.txt 文件的 keyWords 列表中搜索第一项。

第三个循环确实返回基于第二个列表提取并尝试迭代的 sessionID 出现的结果(这给出了一个超出范围的异常,因为 i 永远不会小于 sessionID 列表的长度,因为sessionID 只有 1 个值)。

程序确实成功地写入并命名了新的日志文件,日期时间后跟 ParsedLog.txt。

【问题讨论】:

  • 这是 j+=1 #advance the keyWords array 否则。如果这是真的if keyWords[j] in line:,它将不会执行。也许这就是原因?
  • 这里的预期行为是什么?对于每一行,查找至少一次出现的关键字,并保存 sessionID?或者对于每一行和每个关键字,如果在该行中找到关键字,则保存 sessionID(即您可以多次保存同一行?)
  • 您的第一个断言,“对于每一行,查找至少一次出现的关键字,并保存 sessionID?”是正确的。基本上,寻找奇怪的登录行为,然后保存发生奇怪登录行为的 sessionID。

标签: python python-3.x


【解决方案1】:

在我看来,您的第二个循环需要一个内部循环而不是内部 if 语句。例如

for line in FILE:
    for word in keyWords:
            if word in line:
                    parseString = line[29:35] #pulling in session ID
                    sessionID.append(parseString) #saving session IDs to a list
                    break # Assuming there will only be one keyword per line, else remove this
    logLine +=1 #for debugging purposes when testing
importFile2.close()      
print(sessionID) #for debugging purposes when testing        

假设我理解正确,就是这样。

【讨论】:

  • 我想你的意思是if word in line 不是if keyWords[j] in line
  • 非常感谢,我发现我现在的循环不正确。
【解决方案2】:

如果 elif 永远不是 True,则您永远不会增加 j,因此您要么需要始终递增,要么检查 elif 语句是否实际评估为 True

   for line in FILE:
        if keyWords[j] in line:
                parseString = line[29:35] #pulling in session ID
                sessionID.append(parseString) #saving session IDs to a list
        elif importFile == '' and j < len(keyWords):  #if importFile is at end of file and we are not at the end of the array
                importFile.seek(0) #goes back to the start of the file
        j+=1     # always increase

查看上面的循环,您在代码的前面使用importFile = open('rawLog.txt', 'r') 创建了文件对象,因此比较elif importFile == '' 永远不会是True,因为importFile 是文件对象而不是字符串。

您分配了FILE = importFile.readlines(),这样确实耗尽了创建文件列表的迭代器,您importFile.seek(0),但实际上并没有在任何地方再次使用文件对象。

所以基本上你在FILE 上循环一次,j 永远不会增加,然后你的代码会移动到下一个块。

您真正需要的是嵌套循环,使用any 查看每行中是否有来自 keyWords 的任何单词,然后忘记您的 elif :

for line in FILE: 
    if any(word in line for word in keyWords):
            parseString = line[29:35] #pulling in session ID
            sessionID.append(parseString) #saving session IDs to a list

同样的逻辑适用于你的下一个循环:

for line in FILE:
    if any(sess in line[29:35] for sess in sessionID ): #checking if the sessionID matches (doing it this way since I ran into issues where some sessionIDs matched parts of the log file that were not sessionIDs
            exportFile.write(line)#writing the log file line to a new text file

holderString = line 什么都不做 bar 引用同一对象行,因此您可以简单地 exportFile.write(line) 并忘记分配。

在旁注中,变量等使用小写和下划线。holderString -&gt; holder_string 并使用with 打开文件是最好的,因为它也会关闭它们。

with open('rawLog.txt') as import_file:
    log_lines = import_file.readlines()

我还将FILE 更改为log_lines,使用更具描述性的名称使您的代码更易于理解。

【讨论】:

  • 感谢您对我搞砸的解释!
  • @AddisonWilson,不用担心,使用 any 是 Python 的方式来做你想做的事,它可以更好地完成你接受的答案的工作
猜你喜欢
  • 2021-03-09
  • 1970-01-01
  • 2016-03-01
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 2020-05-29
  • 1970-01-01
相关资源
最近更新 更多