【问题标题】:How can I change the output of this function into a dictionary? [duplicate]如何将此函数的输出更改为字典? [复制]
【发布时间】:2022-01-09 21:35:11
【问题描述】:

我编写了一个包含正则表达式的函数来分隔txt 文件的一些特殊部分。代码工作正常,但我想得到一个字典作为输出,长度应该是 979:

import re

def logs():
    with open("C:/Users/ASUS/Desktop/logdata.txt", "r") as file:
        logdata = file.read()

    pattern = ''' 
    (?P<host>\d{1,}\.\d{1,}\.\d{1,}\.\d{1,})    # host name
    \s+\S+\s+
    (?P<user_name>(?<=-\s)(\w+|-)(?=\s))\s+\[   # user_name
    (?P<time>([^[]+))\]\s+"                     # time
    (?P<request>[^"]+)"                         # request
    '''

    for item in re.finditer(pattern, logdata, re.VERBOSE):
        print(item.groupdict())

这个函数应该变成这样的文本:

146.204.224.152 - feest6811 [21/Jun/2019:15:45:24 -0700] "POST /incentivize HTTP/1.1" 302 4622

到此捕获hostuser_name 等:

{"host":"146.204.224.152", 
 "user_name":"feest6811", 
 "time":"21/Jun/2019:15:45:24 -0700",
 "request":"POST /incentivize HTTP/1.1"}

我该怎么做?

【问题讨论】:

  • 目前输出什么?
  • @mkrieger1 感谢您的回答。我只是使用 my_list = re.findall(pattern, logdata, re.VERBOSE) 而不是 for 循环,它会输出一个列表。
  • 你的代码是print(item.groupdict()),而不是my_list = ...。它输出什么?
  • 我刚刚编辑了代码。请检查它知道。它返回一个列表。
  • 当你不想要一个列表时,你为什么要更改代码以返回一个列表?如果你想要一本字典,为什么不保留打印字典的代码?

标签: python python-3.x dictionary for-loop


【解决方案1】:

晚了,但这个详细的正则表达式也可以(返回字典列表]

import re
def logs():
    with open("C:/Users/ASUS/Desktop/logdata.txt", "r") as file:
        logdata = file.read()
    
    pattern = """
    (?P<host>[\d\.]*)       #IP host
    (\ -\ )                 #followed by 
    (?P<user_name>[\w-]*)   #user name
    (\ *\[)                 #followed by 
    (?P<time>[^\]]*)        #time
    (\]\ *")                #followed by 
    (?P<request>[^\"]*)     #request"""

    return [item.groupdict() for item in re.finditer(pattern, logdata, re.VERBOSE)]

【讨论】:

    【解决方案2】:

    直接使用groupdict()即可:

    import re 
    
    def rtr_dict(txt):
      pattern = ''' 
      (?P<host>\d{1,}\.\d{1,}\.\d{1,}\.\d{1,})   # host name
      \s+\S+\s+
      (?P<user_name>(?<=-\s)(\w+|-)(?=\s))\s+\[   # user_name
      (?P<time>([^[]+))\]\s+"   # time
      (?P<request>[^"]+)"   # request
      '''
      
      if m:=re.match(pattern, txt, flags=re.VERBOSE):
        return m.groupdict()
    
    tgt='146.204.224.152 - feest6811 [21/Jun/2019:15:45:24 -0700] "POST /incentivize HTTP/1.1" 302 4622'
    
    
    >>>rtr_dict(tgt)
    {'host': '146.204.224.152', 'user_name': 'feest6811', 'time': '21/Jun/2019:15:45:24 -0700', 'request': 'POST /incentivize HTTP/1.1'}
    

    请你告诉我,我怎样才能做到不止一行,就像我使用 for 循环那样。

    给定:

    tgt='''146.204.224.152 - feest6811 [21/Jun/2019:15:45:24 -0700] "POST /incentivize HTTP/1.1" 302 4622
    146.204.224.153 - feest6811 [21/Jun/2019:15:45:24 -0700] "POST /incentivize HTTP/1.1" 302 4623
    146.204.224.154 - feest6811 [21/Jun/2019:15:45:24 -0700] "POST /incentivize HTTP/1.1" 302 4624'''
    

    如果你有多个匹配,你可以返回一个字典列表:

    def rtr_dict(txt):
      pattern = ''' 
      (?P<host>\d{1,}\.\d{1,}\.\d{1,}\.\d{1,})   # host name
      \s+\S+\s+
      (?P<user_name>(?<=-\s)(\w+|-)(?=\s))\s+\[   # user_name
      (?P<time>([^[]+))\]\s+"   # time
      (?P<request>[^"]+)"   # request
      '''
      
      return [m.groupdict() for m in re.finditer(pattern, txt, flags=re.VERBOSE)]
    
    >>> rtr_dict(tgt)
    [{'host': '146.204.224.152', 'user_name': 'feest6811', 'time': '21/Jun/2019:15:45:24 -0700', 'request': 'POST /incentivize HTTP/1.1'}, {'host': '146.204.224.153', 'user_name': 'feest6811', 'time': '21/Jun/2019:15:45:24 -0700', 'request': 'POST /incentivize HTTP/1.1'}, {'host': '146.204.224.154', 'user_name': 'feest6811', 'time': '21/Jun/2019:15:45:24 -0700', 'request': 'POST /incentivize HTTP/1.1'}]
    

    或者使用生成器:

    def rtr_dict(txt):
      pattern = ''' 
      (?P<host>\d{1,}\.\d{1,}\.\d{1,}\.\d{1,})   # host name
      \s+\S+\s+
      (?P<user_name>(?<=-\s)(\w+|-)(?=\s))\s+\[   # user_name
      (?P<time>([^[]+))\]\s+"   # time
      (?P<request>[^"]+)"   # request
      '''
      
      for m in re.finditer(pattern, txt, flags=re.VERBOSE):
        yield m.groupdict()
    
    >>> list(rtr_dict(tgt))
    # same list of dicts...
    

    【讨论】:

    • 非常感谢。输出正是我想要的。请你告诉我,我怎样才能做到不止一行,就像我使用 for 循环那样。
    • 更新:使用列表理解或生成器...
    • 这是完美的。非常感谢你。我对这个概念很陌生。如果您可以在列表理解部分添加一些注释,我将不胜感激。不过,我会及时了解它们。再次感谢你:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    • 2020-01-21
    相关资源
    最近更新 更多