2024-04-25 04:13:17 发布
网友
我有一个数据如下:
data = 'person(firstame="bob", lastname="stewart", dob="2010-0206", hobbies=["reading, singing", "drawing"], is_minor=True)'
我写的语法分析规则如下:
我的问题有三个:
你应该把它拆开,这样它就不会太依赖文字了。。。因此,寻找“X=Y”这样的标记,使其更通用。。。在
或者,另一个选项(因为它看起来像是在解析一个Python函数调用),如下所示:
data = 'person(firstame="bob", lastname="stewart", dob="2010-0206", hobbies=["reading, singing", "drawing"], is_minor=True)' import ast d = {} for kw in ast.parse(data).body[0].value.keywords: if isinstance(kw.value, ast.List): d[kw.arg] = [el.s for el in kw.value.elts] else: d[kw.arg] = getattr(kw.value, {ast.Name: 'id', ast.Str: 's'}[type(kw.value)]) # {'dob': '2010-0206', 'lastname': 'stewart', 'is_minor': 'True', 'firstame': 'bob', 'hobbies': ['reading, singing', 'drawing']}
您发布的代码中有一些小的错误(firstame="bob"在data vs.firstname="bob",lastnamevs.last),但是在清理它们之后,它看起来相当不错。如果打印出结果,您将得到:
firstame="bob"
firstname="bob"
lastname
last
['firstname', 'bob', 'lastname', 'stewart', 'dob', '2010-0206', 'hobbies', 'reading, singing', 'drawing', 'is_minor', 'True']
首先,让我建议,正如您将list_of_names(来自您之前的SO问题pyparsing string of quoted names)定义为可能的值类型一样,您需要定义一个布尔值来解析真/假值。使用oneOf很好,让我们添加一个解析操作,将字符串“True”和“False”转换为实际的Python布尔值:
list_of_names
oneOf
这类似于在quotedString上使用removeQuotes。在
removeQuotes
现在,解析的结果如下所示:
['firstname', 'bob', 'lastname', 'stewart', 'dob', '2010-0206', 'hobbies', 'reading, singing', 'drawing', 'is_minor', True]
注意,True现在不是一个字符串,而是Python值True(该值周围没有引号)。在
True
现在进入问题的第一部分,如何使其成为dict.Pyparsing允许您为语法的不同部分定义结果名称,以便在数据被解析后,您可以按名称访问这些值。执行此操作的语法过去是调用方法setResultsName:
setResultsName
my_data = person_start + first.setResultsName("firstname") + last.setResultsName("lastname") + ...
我发现这有点麻烦,而且对于所有“.setResultsName”方法调用,表达式更难阅读。所以不久前,我更改了API以接受以下语法:
my_data = person_start + first("firstname") + last("lastname") + ...
但是您定义的first,last等不仅仅包含值,它们还包括标签。在
first
简化语法的一种方法是创建一个自己的小helper方法,我们称之为named_parameter:
named_parameter
def named_parameter(label, paramtype): expr = Literal(label) + Suppress('=') + paramtype(label) return expr
请注意,label用于指定文本字符串和值的结果名称。现在您可以将语法定义为:
label
first = named_parameter("firstname", quotedString) last = named_parameter("lastname", quotedString) dob = named_parameter("dob", quotedString) hobbies = named_parameter("hobbies", Suppress("[") + list_of_names + Suppress("]")) is_minor = named_parameter("is_minor", boolean_value)
使用名为的值,您可以使用Python dict访问解析结果:
print result["firstname"] print result["hobbies"]
印刷品:
bob ['reading, singing', 'drawing']
或者,如果愿意,也可以使用对象属性表示法:
print result.firstname print result.hobbies
为了回答问题的第二部分,您询问了如何处理参数可能出现故障的情况。最简单的方法是再次使用delimitedList:
delimitedList
parameter = first | last | dob | hobbies | is_minor my_data = person_start + delimitedList(parameter) + person_end
这不是一个严格的解析器,它将接受不包含所有参数的参数列表,或者包含重复参数的列表。但对于现有的有效代码,它将解析具有任意顺序的参数的列表。在
这是最后一个解析器:
quotedString.setParseAction(removeQuotes) list_of_names = delimitedList(quotedString) boolean_value = oneOf("True False").setParseAction(lambda t: t[0]=='True') def named_parameter(label, paramtype): expr = Literal(label) + Suppress('=') + paramtype(label) return expr person_start = Literal("person(").suppress() first = named_parameter("firstname", quotedString) last = named_parameter("lastname", quotedString) dob = named_parameter("dob", quotedString) hobbies = named_parameter("hobbies", Suppress("[") + list_of_names + Suppress("]")) is_minor = named_parameter("is_minor", boolean_value) person_end = Suppress(")") comma = Literal(",").suppress() parameter = first | last | dob | hobbies | is_minor my_data = person_start + delimitedList(parameter) + person_end
你应该把它拆开,这样它就不会太依赖文字了。。。因此,寻找“X=Y”这样的标记,使其更通用。。。在
或者,另一个选项(因为它看起来像是在解析一个Python函数调用),如下所示:
您发布的代码中有一些小的错误(
firstame="bob"
在data vs.firstname="bob"
,lastname
vs.last
),但是在清理它们之后,它看起来相当不错。如果打印出结果,您将得到:首先,让我建议,正如您将
^{pr2}$list_of_names
(来自您之前的SO问题pyparsing string of quoted names)定义为可能的值类型一样,您需要定义一个布尔值来解析真/假值。使用oneOf
很好,让我们添加一个解析操作,将字符串“True”和“False”转换为实际的Python布尔值:这类似于在quotedString上使用
removeQuotes
。在现在,解析的结果如下所示:
注意,True现在不是一个字符串,而是Python值
True
(该值周围没有引号)。在现在进入问题的第一部分,如何使其成为dict.Pyparsing允许您为语法的不同部分定义结果名称,以便在数据被解析后,您可以按名称访问这些值。执行此操作的语法过去是调用方法
setResultsName
:我发现这有点麻烦,而且对于所有“.setResultsName”方法调用,表达式更难阅读。所以不久前,我更改了API以接受以下语法:
但是您定义的
first
,last
等不仅仅包含值,它们还包括标签。在简化语法的一种方法是创建一个自己的小helper方法,我们称之为
named_parameter
:请注意,
label
用于指定文本字符串和值的结果名称。现在您可以将语法定义为:使用名为的值,您可以使用Python dict访问解析结果:
印刷品:
或者,如果愿意,也可以使用对象属性表示法:
为了回答问题的第二部分,您询问了如何处理参数可能出现故障的情况。最简单的方法是再次使用
delimitedList
:这不是一个严格的解析器,它将接受不包含所有参数的参数列表,或者包含重复参数的列表。但对于现有的有效代码,它将解析具有任意顺序的参数的列表。在
这是最后一个解析器:
相关问题 更多 >
编程相关推荐