Python 多行正则表达式 - 多个标签和条件
Python mutliline regex - Multiple Tags and Conditions
我不得不承认,我的 Regex 质量很差,我(在这种情况下)通过其他解决方案避免了它们。但是,在这种情况下,为了稳定和清洁,我真的很想有一个解决方案。
输入文件看起来如下:
MAIN: name
attr1: str
attr2: str
attr3: str
SUB: name
attr1: str
attr2: str
attr3: str
MAIN: name
attr1: str
attr2: str
SUB: name
attr1: str
attr2: str
SUB: name
attr1: str
SUB: name
attr1: str
attr2: str
attr3: str
条目始终以未缩进的 MAIN
开头,后跟 collon
和 name
。
以下是 1 to N
个缩进键值对。
然后有 0 to N
个未缩进的条目 SUB:name
,然后是缩进的属性。
每个条目之间有一个空行(无论MAIN
还是SUB
。
Output
应该如下
output = {main_name:
{
'attr1': str,
'attr2': str,
...
'subs': [
{
'name': sub_name,
'attr1': str,
...
},
{...}
]
}
main_name2:
{
...
}
}
我目前的做法是这样的:
entries = input.split('\n\n')
entries = [entry.replace(" ","").split("\n") for entry in entries]
entries = [attribute.split(":") for entry in entries for attribute in entry]
然后使用大量 if 和 else 遍历项目以生成所描述的键值结构。
有人可以提示我一种优雅的方式来处理这样的结构,实际上定义非常明确并且应该可以处理:)
干杯,谢谢你们!
对于这样的结构,老实说,我不会直接使用正则表达式来读取文件。数据结构看起来像嵌套的 dictionary.
如何创建一个字典对象并在读取文件时填充键、子字典和子键?
您可以看到几个从文本文件 here.
填充 python 词典的示例
您可以逐行迭代,一边构建结构。您只需要跟踪您当前的位置,以便将属性放在它们所属的位置:
def parse_data(data):
out = {}
for line in data.splitlines():
if not line:
continue
if line.startswith("MAIN"):
name = line[6:]
out[name] = {}
current = out[name]
elif line.startswith("SUB"):
subname = line[5:]
out[name].setdefault('subs', []).append({'name': subname})
current = out[name]['subs'][-1]
elif line.startswith(' '):
attr, value = line[2:].split(':')
value = value.strip()
current[attr] = value
return out
data = """
MAIN: main1
attr1: str
attr2: str
attr3: str
SUB: 1.1
attr1: str
attr2: str
attr3: str
MAIN: main2
attr1: str
attr2: str
SUB: 2.1
attr1: str
attr2: str
SUB: 2.2
attr1: str
SUB: 2.3
attr1: str
attr2: str
attr3: str
"""
输出:
print(parse_data(data))
{'main1': {'attr1': 'str',
'attr2': 'str',
'attr3': 'str',
'subs': [{'name': '1.1', 'attr1': 'str', 'attr2': 'str', 'attr3': 'str'}]},
'main2': {'attr1': 'str',
'attr2': 'str',
'subs': [{'name': '2.1', 'attr1': 'str', 'attr2': 'str'},
{'name': '2.2', 'attr1': 'str'},
{'name': '2.3', 'attr1': 'str', 'attr2': 'str', 'attr3': 'str'}]}}
我不得不承认,我的 Regex 质量很差,我(在这种情况下)通过其他解决方案避免了它们。但是,在这种情况下,为了稳定和清洁,我真的很想有一个解决方案。 输入文件看起来如下:
MAIN: name
attr1: str
attr2: str
attr3: str
SUB: name
attr1: str
attr2: str
attr3: str
MAIN: name
attr1: str
attr2: str
SUB: name
attr1: str
attr2: str
SUB: name
attr1: str
SUB: name
attr1: str
attr2: str
attr3: str
条目始终以未缩进的 MAIN
开头,后跟 collon
和 name
。
以下是 1 to N
个缩进键值对。
然后有 0 to N
个未缩进的条目 SUB:name
,然后是缩进的属性。
每个条目之间有一个空行(无论MAIN
还是SUB
。
Output
应该如下
output = {main_name:
{
'attr1': str,
'attr2': str,
...
'subs': [
{
'name': sub_name,
'attr1': str,
...
},
{...}
]
}
main_name2:
{
...
}
}
我目前的做法是这样的:
entries = input.split('\n\n')
entries = [entry.replace(" ","").split("\n") for entry in entries]
entries = [attribute.split(":") for entry in entries for attribute in entry]
然后使用大量 if 和 else 遍历项目以生成所描述的键值结构。
有人可以提示我一种优雅的方式来处理这样的结构,实际上定义非常明确并且应该可以处理:)
干杯,谢谢你们!
对于这样的结构,老实说,我不会直接使用正则表达式来读取文件。数据结构看起来像嵌套的 dictionary.
如何创建一个字典对象并在读取文件时填充键、子字典和子键?
您可以看到几个从文本文件 here.
填充 python 词典的示例您可以逐行迭代,一边构建结构。您只需要跟踪您当前的位置,以便将属性放在它们所属的位置:
def parse_data(data):
out = {}
for line in data.splitlines():
if not line:
continue
if line.startswith("MAIN"):
name = line[6:]
out[name] = {}
current = out[name]
elif line.startswith("SUB"):
subname = line[5:]
out[name].setdefault('subs', []).append({'name': subname})
current = out[name]['subs'][-1]
elif line.startswith(' '):
attr, value = line[2:].split(':')
value = value.strip()
current[attr] = value
return out
data = """
MAIN: main1
attr1: str
attr2: str
attr3: str
SUB: 1.1
attr1: str
attr2: str
attr3: str
MAIN: main2
attr1: str
attr2: str
SUB: 2.1
attr1: str
attr2: str
SUB: 2.2
attr1: str
SUB: 2.3
attr1: str
attr2: str
attr3: str
"""
输出:
print(parse_data(data))
{'main1': {'attr1': 'str',
'attr2': 'str',
'attr3': 'str',
'subs': [{'name': '1.1', 'attr1': 'str', 'attr2': 'str', 'attr3': 'str'}]},
'main2': {'attr1': 'str',
'attr2': 'str',
'subs': [{'name': '2.1', 'attr1': 'str', 'attr2': 'str'},
{'name': '2.2', 'attr1': 'str'},
{'name': '2.3', 'attr1': 'str', 'attr2': 'str', 'attr3': 'str'}]}}