在Python中解析键值日志

在Python中解析键值日志,python,Python,我有一个如下所示的系统日志: { a = 1 b = 2 c = [ x:1, y:2, z:3, ] d = 4 } 我想在Python中将其解析为一个dictionary对象,并使用=拆分键值对。同时,由[]包围的数组也被保留。我希望尽可能保持这种通用性,以便解析也可以保存一些未来的变体 到目前为止我所尝试的(代码将被编写):按“=”将每一行拆分为键值对,确定[and]开

我有一个如下所示的系统日志:

{
    a = 1
    b = 2
    c = [
            x:1,
            y:2,
            z:3,
        ]
    d = 4
}
我想在Python中将其解析为一个dictionary对象,并使用=拆分键值对。同时,由[]包围的数组也被保留。我希望尽可能保持这种通用性,以便解析也可以保存一些未来的变体


到目前为止我所尝试的(代码将被编写):按“=”将每一行拆分为键值对,确定[and]开始和结束的位置,然后按“:”将中间的行拆分为键值对。这似乎有点硬编码。。有更好的主意吗?

可能有更好的答案,但我会利用您所有的字典键都处于相同的缩进级别。由于列表结构有点奇怪(它看起来像是列表和字典的交叉点),所以没有一种明显的方法可以通过新行分割、JSON加载或诸如此类的事情来实现这一点

下面是一个基于缩进级别解析键的实现:

import re

log = '''{
    a = 1
    b = 2
    c = [
            x:1,
            y:2,
            z:3,
        ]
    d = 4
}'''
log_lines = log.split('\n')[1:-1]  # strip bracket lines
KEY_REGEX = re.compile(r'    [^ ]')

d = {}
current_pair = ''
for i, line in enumerate(log_lines):
    if KEY_REGEX.match(line):
        if current_pair:
            key, value = current_pair.split('=')
            d[key.strip()] = value.strip()
        current_pair = line
    else:
        current_pair += line.strip()

if current_pair:
    key, value = current_pair.split('=')
    d[key.strip()] = value.strip()

print(d)
输出

{'d': '4', 'c': '[x:1,y:2,z:3,]', 'a': '1', 'b': '2'}

也许有一个更好的答案,但我会利用所有字典键都处于相同缩进级别的优势。由于列表结构有点奇怪(它看起来像是列表和字典的交叉点),所以没有一种明显的方法可以通过新行分割、JSON加载或诸如此类的事情来实现这一点

下面是一个基于缩进级别解析键的实现:

import re

log = '''{
    a = 1
    b = 2
    c = [
            x:1,
            y:2,
            z:3,
        ]
    d = 4
}'''
log_lines = log.split('\n')[1:-1]  # strip bracket lines
KEY_REGEX = re.compile(r'    [^ ]')

d = {}
current_pair = ''
for i, line in enumerate(log_lines):
    if KEY_REGEX.match(line):
        if current_pair:
            key, value = current_pair.split('=')
            d[key.strip()] = value.strip()
        current_pair = line
    else:
        current_pair += line.strip()

if current_pair:
    key, value = current_pair.split('=')
    d[key.strip()] = value.strip()

print(d)
输出

{'d': '4', 'c': '[x:1,y:2,z:3,]', 'a': '1', 'b': '2'}

这可以很容易地简化为YAML
pip安装pyyaml
,然后进行如下设置:

import string, yaml

data = """
{
    a = 1
    b = 2
    c = [
            x:1,
            y:2,
            z:3,
        ]
    d = 4
}
"""
通过此设置,您可以使用以下方法解析数据:

data2 = data.replace(":", ": ").replace("=", ":").replace("[","{").replace("]","}")

lines = data2.splitlines()
for i, line in enumerate(lines):
    if len(line)>0 and line[-1] in string.digits and not line.endswith(",") or i < len(lines) - 1 and line.endswith("}"):
        lines[i] += ","
data3 = "\n".join(lines)
yaml.load(data3) # {'a': 1, 'b': 2, 'c': {'x': 1, 'y': 2, 'z': 3}, 'd': 4}
接下来,我们有一个
for
循环。这只是负责在缺少逗号的行之后添加逗号。缺少for循环的两种情况是: -它们在一个数值之后不存在 -他们在结束时缺席

我们使用
len(line)>0和string.digits中的第[-1]行匹配第一种情况(行中的最后一个字符是数字)

使用
i
匹配第二种情况。这将检查该行是否以
}
结尾,并检查该行是否不是最后一行,因为YAML不允许在最后一个括号后使用逗号

循环之后,我们有:

{
    a : 1,
    b : 2,
    c : {
            x: 1,
            y: 2,
            z: 3,
        },
    d : 4,
}
这是有效的YAML。剩下的就是
yaml.load
,您就有了一个python
dict


如果有什么不清楚的地方,请留下评论,我很乐意详细说明。

这可以很容易地简化为YAML
pip安装pyyaml
,然后进行如下设置:

import string, yaml

data = """
{
    a = 1
    b = 2
    c = [
            x:1,
            y:2,
            z:3,
        ]
    d = 4
}
"""
通过此设置,您可以使用以下方法解析数据:

data2 = data.replace(":", ": ").replace("=", ":").replace("[","{").replace("]","}")

lines = data2.splitlines()
for i, line in enumerate(lines):
    if len(line)>0 and line[-1] in string.digits and not line.endswith(",") or i < len(lines) - 1 and line.endswith("}"):
        lines[i] += ","
data3 = "\n".join(lines)
yaml.load(data3) # {'a': 1, 'b': 2, 'c': {'x': 1, 'y': 2, 'z': 3}, 'd': 4}
接下来,我们有一个
for
循环。这只是负责在缺少逗号的行之后添加逗号。缺少for循环的两种情况是: -它们在一个数值之后不存在 -他们在结束时缺席

我们使用
len(line)>0和string.digits中的第[-1]行匹配第一种情况(行中的最后一个字符是数字)

使用
i
匹配第二种情况。这将检查该行是否以
}
结尾,并检查该行是否不是最后一行,因为YAML不允许在最后一个括号后使用逗号

循环之后,我们有:

{
    a : 1,
    b : 2,
    c : {
            x: 1,
            y: 2,
            z: 3,
        },
    d : 4,
}
这是有效的YAML。剩下的就是
yaml.load
,您就有了一个python
dict


如果有什么不清楚的地方,请留下评论,我很乐意详细说明。

我建议您熟悉一下。另外,你的键值对不是用逗号分隔,而是用换行符分隔吗?@NathanielFord,正是这种格式。你能澄清一下“保留”是什么意思吗?我建议你熟悉一下。还有,你的键值对不是用逗号分隔,而是用换行符分隔吗?@NathanielFord,就是这个格式。你能澄清一下你所说的“保留”是什么意思吗?我不清楚他所说的“保留”是什么意思,你认为这意味着把它作为字符串保留吗?这对我来说似乎很奇怪。我不知道如何在列表中存储看起来像键值对的东西,除非他想要它们作为元组?这将是相当简单的,但我做了最一般的事情,因为没有澄清。好的。您认为我应该在回答中提供一个替代实现吗?我只是把它作为一个子目录进行解析,并假设“保留”意味着将它作为一个子目录而不是合并到主目录中。我认为假设一本字典是完全合理的:)可能最好在投入更多工作之前等待OP的澄清。我不清楚他所说的“保留”是什么意思你认为那意味着把它当作一根绳子?这对我来说似乎很奇怪。我不知道如何在列表中存储看起来像键值对的东西,除非他想要它们作为元组?这将是相当简单的,但我做了最一般的事情,因为没有澄清。好的。您认为我应该在回答中提供一个替代实现吗?我只是把它作为一个子目录进行解析,并假设“保留”意味着将它作为一个子目录而不是合并到主目录中。我认为假设一个字典是完全合理的:)在投入更多的工作之前,可能最好等待OP的澄清。