【问题标题】:Taking Information From Line Iteration Using Regex and Storing Data in Nested Dictionaries使用正则表达式从行迭代中获取信息并将数据存储在嵌套字典中
【发布时间】:2019-12-22 03:55:45
【问题描述】:

概述

我正在尝试从文件中获取信息(逐行读取),使用正则表达式将数据拆分为字典字典(嵌套字典),其中格式为

{
IP1: {
    Message1 {count},
    Message2 {count}, 
    Message3 {count}, 
    etc.
    }, 
IP2: {
    Message1 {count}, 
    Message2 {count}, 
    Message3 {count}, 
    etc.
    }, 
etc.
}.

我只是被困在获取这些信息,并将其放入字典字典中,每条消息都有一个计数。

我有一个基本的工作原型,它存储 {IP1: {message1}、IP2: {message2} 等},但如果数字已经在字典中,它不会存储其他消息。我正在使用正则表达式过滤掉噪音,只关注信号(我需要的),它没有任何问题。但是我被数据结构部分所束缚,并且对消息进行计数。

我尝试过的

Create nested dictionary on the fly in Python

https://www.youtube.com/watch?v=ygRINYibL74

How do you create nested dict in Python?

https://www.youtube.com/watch?v=K8L6KVGG-7o

https://www.youtube.com/watch?v=c9HbsUSWilw

https://medium.com/factory-mind/regex-tutorial-a-simple-cheatsheet-by-examples-649dc1c3f285

https://docs.python.org/2/library/re.html

我尝试创建一个 pandas 数组和 numpy 数组,但它仍然对我不起作用。我使用了许多我没有添加书签的其他来源,试图帮助我,但我记不住它们。

示例代码

def cleanData(rawData):
     cleanIP = ipSubstitution(rawData)
     cleanPacket = packetSubstitution(cleanIP)
     cleanMessage = messageSubstitution(cleanPacket)
     cleanRepeats = repeatedSubstition(cleanMessage)
     cleanHexadecimal = hexadecimalSubstition(cleanRepeats)
     cleanTime = removeTime(cleanHexadecimal)
     return cleanTime

def ipSubstitution(ip):
     ip_exchange = re.compile(r"[a-z]{2,4}=[0-9]{0,3}.[0-9]{0,3}.[0-9]{0,3}.[0-9]{0,3}")
     replaceIP = "XXX.XXX.XXX.XXX"
     ipReturn = re.sub(ip_exchange, replaceIP, ip)
     return ipReturn

def packetSubstitution(packet):
     packetSubstitute = re.compile(r"[a-z]{2,4}_[a-z]{2,4}_[a-z]{2,4}_[a-z]{2,4}_[a-z]{2,4}")
     replacePacket = "XX_XX_XXX_XXXX_XXX"
     packetReturn = re.sub(packetSubstitute, replacePacket, packet)
     return packetReturn

def messageSubstitution(message):
     messageExchange = re.compile(r"[a-z]{0,5}_[a-z]{0,5}_[a-z]{0,5}_[a-z]{0,5}_[a-z]{0,5}.+")
     replaceMessage = "XX_XXX_XXXXX_XXXXX_XXXXX"
     messageReturn = re.sub(messageExchange, replaceMessage, message)
     return messageReturn

def repeatedSubstition(repeatedMessage):
     repeatedExchange = re.compile(r"[a-z]{7}\s[a-z]{8}.+")
     replaceRepeated = "XXXXXXX"
     repeatedReturn = re.sub(repeatedExchange, replaceRepeated, repeatedMessage)
     return repeatedReturn

def hexadecimalSubstition(hexadecimalMessage):
     hexadecimalExchange = re.compile(r"[a-z0-9]{12}\s[ok]{2}")
     replaceHexadecimal = "XXXXXXXXXXXX"
     hexadecimalReturn = re.sub(hexadecimalExchange, replaceHexadecimal, hexadecimalMessage)
     return hexadecimalReturn

def removeTime(timeRemoval):
     timeExchange = re.compile(r"([A-Z][a-z][a-z]\s\d{2})+\s+(\d{2}\:\d{2}\:\d{2})+\s")
     replaceTime = ""
     timeReturn = re.sub(timeExchange, replaceTime, timeRemoval)
     return timeReturn

def matchExpression(analysisDict,rawText):
     d = analysisDict
     regexMatch = re.compile(
     r"(?P<IP_Address>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:)+\s" +
     "(?P<Message>.+)")
     matchedText = re.match(regexMatch, rawText)
     for _ in rawText:
          count = 0
          ip = matchedText.group("IP_Address")
          message = matchedText.group("Message")
          d.setdefault(ip, {})["Message"] = message
          d[ip][message] = count + 1
          // wanting to add count here but given an error regarding
          // string can not hold variable
          for doe in d:
               if numbers == d[doe]:
                    for ray in d[doe]:
                         if message == d[doe][ray]:
                              d[doe][ray] = count + 1

analysisDict = {}

textFile = open('text_file', 'r')

for line in textFile:
   //cleanData is a function calling other functions to
   //clear away unneeded text
    cleanData(line)
    matchExpression(analysisDict,cleanData(line))

我一直在弄清楚如何将多个消息添加到每个数字,并将计数添加到每个消息。

如果有人可以帮助我,我将非常感激。

2019 年 8 月 18 日更新

示例输入

Jan 29 05:23:11 11.111.11.111: devmgmt: ah_tv_alg_proc_pkt: Packet(src=10.45.27.220, dst=69.25.139.140) dropped
Jan 29 05:23:11 11.111.11.111: devmgmt: ah_tv_alg_proc_pkt: Packet(src=10.45.27.89, dst=69.25.139.140) dropped
Jan 29 05:23:11 22.222.22.222: system: Fetch shared memory 1000 of size 182224, address at 0xb6254000
Jan 29 05:23:11 11.111.11.111: message repeated 8 times
Jan 29 05:23:11 11.111.11.111: devmgmt: ah_tv_alg_proc_pkt: Packet(src=10.45.27.231, dst=69.25.139.140) dropped
Jan 29 05:23:11 22.222.22.222: security: Admin "<admin>" successfully logged in
Jan 29 05:23:11 11.111.11.111: message repeated 15 times
Jan 29 05:23:11 11.111.11.111: devmgmt: ah_tv_alg_proc_pkt: Packet(src=10.45.27.220, dst=69.25.139.140) dropped
Jan 29 05:23:11 11.111.11.111: devmgmt: ah_tv_alg_proc_pkt: Packet(src=10.45.27.231, dst=69.25.139.140) dropped
Jan 29 05:23:11 11.111.11.111: devmgmt: ah_tv_alg_proc_pkt: Packet(src=10.45.27.217, dst=69.25.139.140) dropped
Jan 29 05:23:11 11.111.11.111: devmgmt: ah_tv_alg_proc_pkt: Packet(src=10.45.27.231, dst=69.25.139.140) dropped
Jan 29 05:23:11 22.222.22.222: security: admin:<save config current http://11.11.130.145:0000/run-config>

正则表达式之后

"IP1: Message"
"IP2: Message"
"IP1: different message"
"IP2: different message"
etc.

我需要什么帮助

  • 每个 IP 地址存储多条消息(目前仅保存一条)

     for _ in rawText:
          count = 0
          ip = matchedText.group("IP_Address")
          message = matchedText.group("Message")
          d.setdefault(ip, {})["Message"] = message
          d[ip][message] = count + 1
          // wanting to add count here but given an error regarding
          // string can not hold variable
    
  • 为每条消息制作一个子字典并存储它们的个人计数

          for doe in d:
               if ip == d[doe]:
                    for ray in d[doe]:
                         if message == d[doe][ray]:
                              d[doe][ray] = count + 1
    

预期输出

{
Number1: {
    message1: {count1}, 
    message2: {count2}
    },
Number2: {
    message1: {count1}, 
    message2: {count2}
    },
etc.
}

实际输出

{'xxx.xxx.xxx.xxx:': {'Message': '...: XX_XX_XXX_XXXX_XXX: Packet(XXX.XXX.XXX.XXX, XXX.XXX.XXX.XXX) dropped'}, 'xxx.xxx.xxx.xxx:': {'Message': '...: admin:<save config current http://xxx.xxx.xxx.xxx:xxxx/zzz-zzzzzz>'}, 'xxx.xxx.xxx.xxx:': {'Message': '...: arbitrator ip is updated from xxx.xxx.xxx.xxx to xxx.xxx.xxx.xxx'}, 'xxx.xxx.xxx.xxx:': {'Message': '[...]: XX_XXX_XXXXX_XXXXX_XXXXX'}, 'xxx.xxx.xxx.xxx:': {'Message': 'application: get ... cancel.'}}

最终更新

看了更多视频后,我只是在追加到数组时使用了 .split(":", 1) 函数,然后创建了一个 Pandas Dataframe,最后添加了一个带有计数的列。从那里,我对我试图解决的问题进行了必要的分析。希望这对以后的其他人有所帮助!

【问题讨论】:

  • 现在看起来你的 atom"Number(\d+):Message([^"]*)" 你能验证一下吗?听着,除非您显示实际的输入样本,否则没有人会帮助您..
  • 我用更清晰的输出编辑了它。问题不在于我的正则表达式,因为我知道它正在获取正确的数据,我的问题是将数据存储到字典中。
  • 我刚刚向您展示了 atom 的概念。它是您一次需要提取的最小数据块,以便完整输入,我不在乎您有多少四重嵌套数组。忘记正则表达式,专注于进行完整的单一数据事务所需的数据。但是,最低限度,需要。相信我,数组很简单。您可能会在循环中获取数据,在其中处理匹配的每个事务。或者,您可以获取所有匹配项 findall() 并稍后在循环中处理它们。
  • 啊,好吧,我很抱歉我不知道原子是什么(谢谢你的澄清)。附加到数组时,我确实获得了所有数据,但我正在尝试制作字典,因为它们似乎更易于数据访问和分析。与数组相比,您必须将 NumberX 与 MessageY 匹配(如果使用两个不同的数组)。从长远来看,我在考虑,这就是为什么我希望将每条消息的计数存储到字典中,与数字匹配。
  • 如果没有完整的(可执行的)代码和可以运行的示例输入,我发现这很难理解。您有一些关于数字和消息的散文,然后是一些带有 IP 地址、“doe”和“ray”的代码,然后是示例输出(在一行上格式化!),其中的字符串没有出现在问题的其他任何地方......还有您能否简化代码以专注于您需要帮助的部分?

标签: python regex string dictionary nested


【解决方案1】:

我想你正在寻找这个:

import collections

TEST_DATA = [
    ("ip1", "message1"),
    ("ip1", "message2"),
    ("ip2", "message3"),
    ("ip1", "message1"),
    ("ip2", "message3"),
]

# This dict maps IPs to Counter objects, with each "counter"
# mapping messages for the given IP to their counts.
counts = collections.defaultdict(collections.Counter)

for ip, msg in TEST_DATA:  # the loop to get the ips and messages is different in your case
    counts[ip][msg] += 1

# If you want, you can convert to plain dicts:
print({ ip: dict(msg_counts) for ip, msg_counts in counts.items() })
# Prints:
#   {'ip1': {'message1': 2, 'message2': 1}, 'ip2': {'message3': 2}}

【讨论】:

  • 感谢您的评论,我认为这有助于解决计数器问题。我是否需要将数据存储到一个数组中,然后创建一个使用正则表达式(在我的matchedText.group 中)进行计数的新函数?那是我遇到最大问题的地方。我知道正则表达式捕获了我的表达式,但我在存储它们以获取计数方面遇到了困难。我用程序中的内容更新了示例代码,并提供了原始数据的摘录。
  • 如果你设法得到正确的 (ip,msg) 对(这样你就可以打印你 Q 的“正则表达式之后”部分之类的东西),你可以通过运行 counts[ip][msg] += 1 行来计算它们假设您之前已初始化 counts,我会在您获得新配对时回答。
猜你喜欢
  • 2015-09-24
  • 2020-09-30
  • 2014-03-31
  • 1970-01-01
  • 2019-09-30
  • 2019-12-30
  • 1970-01-01
  • 2014-09-08
  • 1970-01-01
相关资源
最近更新 更多