【问题标题】:Transform string into Python Dictionary with recursion and regex使用递归和正则表达式将字符串转换为 Python 字典
【发布时间】:2017-01-25 19:01:02
【问题描述】:

我需要将字符串转换为字典。更具体地说,我需要将 Auditd 消息解析为字典。前任: 字符串:

msg=audit(123.123:123): pid=2514 uid=1000 auid=1000 ses=3 subj=random_ex:random_ex:random_ex:d3-d3:w0.c12    30 msg='op=PAM:accounting grantors=pam_unix,pam_localuser acct="lemoney" exe="/usr/bin/sudo" hostname=? a    ddr=? terminal=/dev/pts/0 res=success'

这里有一些替代品:

msg=audit(1234902.147:88): pid=254 uid=1000 auid=1000 ses=3 subj=random_ex:random_ex:random_ex:d3-d3:w0.c12    30 msg='op=PAM:accounting grantors=pam_unix,pam_localuser acct="lemoney" exe="/usr/bin/grep" hostname=? a    ddr=? terminal=/dev/pts/0 res=success'

msg=audit(432787023.324:77): pid=1254 uid=1000 auid=1000 ses=3 subj=random_ex:random_ex:random_ex:d3-d3:w0.c12    30 msg='op=PAM:accounting grantors=pam_unix,pam_localuser acct="lemoney" exe="/usr/bin/tail" hostname=? a    ddr=? terminal=/dev/pts/0 res=success'

我想要的是:

{
  msg: 'audit(...',
  pid: ...,
  uid: ...,
  mess: {
    op: PAM...,
    grantors=pam_unix...
  }
}

我真的很想知道我需要一个正则表达式并且它需要是递归的,但我非常感谢一些帮助。

【问题讨论】:

  • 是的。每一个都是一个单独的条目

标签: python regex dictionary


【解决方案1】:

你去(在一些正则表达式的帮助下):

import re

string = """
msg=audit(1234902.147:88): pid=254 uid=1000 auid=1000 ses=3 subj=random_ex:random_ex:random_ex:d3-d3:w0.c12    30 msg='op=PAM:accounting grantors=pam_unix,pam_localuser acct="lemoney" exe="/usr/bin/grep" hostname=? a    ddr=? terminal=/dev/pts/0 res=success'

msg=audit(432787023.324:77): pid=1254 uid=1000 auid=1000 ses=3 subj=random_ex:random_ex:random_ex:d3-d3:w0.c12    30 msg='op=PAM:accounting grantors=pam_unix,pam_localuser acct="lemoney" exe="/usr/bin/tail" hostname=? a    ddr=? terminal=/dev/pts/0 res=success'
"""

# lines regex
entries = re.compile(r'^msg=.+', re.MULTILINE)

# outer regex
rx = re.compile("""
    ((\w+)='([^']+)') # longer group
    |             # or
    (\w+=\S+)     # single items
    """, re.VERBOSE)

# inner regex
ry = re.compile("(\w+)=(\S+)")

for entry in entries.finditer(string):
  result = dict()
  for match in rx.finditer(entry.group(0)):
    try:
      key, value = match.group(4).split('=')
      result[key] = value
    except:
      #key = match.group(2)

      inner = dict()
      for m in ry.finditer(match.group(3)):
        inner[m.group(1)] = m.group(2)

      result["mess"] = inner

  print(result)

a demo on ideone.com

【讨论】:

  • 不错。非常感谢先生。我之前在处理 for 循环
  • 第一个 msg 值(具有 123.123:123 的那个)被覆盖。我正在重构,但任何帮助将不胜感激
【解决方案2】:

这是一种可能,但在制作过程中没有正则表达式被杀死:

import shlex
from collections import OrderedDict

def split_on_equals_to_dict(string_to_split):
    split_dict = OrderedDict()
    for i, item in enumerate(shlex.split(string_to_split)):
        number_of_equals = item.count('=')
        if number_of_equals == 0:
            split_dict[item] = None
        elif number_of_equals == 1:
            split_dict.update(dict([item.split('=')]))
        else:
            tag, value = tuple(item.split('=', 1))
            split_dict[tag] = split_on_equals_to_dict(value)
    return split_dict

log_str="""audit(123.123:123): pid=2514 uid=1000 auid=1000 ses=3 subj=random_ex:random_ex:random_ex:d3-d3:w0.c12    30 msg='op=PAM:accounting grantors=pam_unix,pam_localuser acct="lemoney" exe="/usr/bin/sudo" hostname=? a    ddr=? terminal=/dev/pts/0 res=success'"""
log_dict = split_on_equals_to_dict(log_str)

提供的字符串有一些歧义。我使用 OrderedDict 处理了这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 2018-08-14
    • 2021-09-16
    相关资源
    最近更新 更多