如何解析没有分隔符的元组?
How to parse tuples that has no delimiters?
我正在使用 pyparser 并想解析包含树结构的文件,其值存储在等号之后,否则没有实际的分隔符。
除了极少数情况下数据存储在多行之外,我已经完成了所有解析,所以我必须重写解析器不要停止从等号到行尾但从等号获取值到另一个等号(或 end
),忽略前面的单词(或忽略 end
)。
数据示例:
(
ItemName = foo
SomeOtherStuff = bar
foo1
foo2
AString1 = ItemName
SomeOtherStuff
)
代码:
equals = Suppress("=")
token = Word(alphanums + "-,./_:*+=#[];")
decimal = Regex(r'-?0|[1-9]\d*').setParseAction(lambda t:int(t[0]))
stringTemplate = token | decimal
sexpList = Group(Suppress("(") + ZeroOrMore(sexp) + Suppress(")"))
sexp = Forward()
这显然行不通
astring = Group(stringTemplate + equals + stringTemplate)
所以我试过这些:
multilineString = Group(token + equals + OneOrMore(stringTemplate) + ~FollowedBy(stringTemplate + equals))
multilineString = Group(token + equals + OneOrMore(stringTemplate) + NotAny(stringTemplate + equals))
multilineString = Group(token + equals + OneOrMore(stringTemplate) + ~(stringTemplate + equals))
但是没有用。我得到的要么是错误,要么是解析器将所有数据吞噬为一条记录。
您在 ~FollowedBy
的正确轨道上,但这些表达式必须是 OneOrMore
重复表达式的一部分。类似于:
multilineString = Group(token + equals + OneOrMore(stringTemplate + ~FollowedBy(equals)))
for match in multilineString.searchString(test):
match.pprint()
其他一些评论:
- 查看
token
、decimal
和 stringTemplate
的定义。就目前而言,您永远不会匹配 decimal
表达式。为避免将 integer
误认为 token
,我建议您将 token
更改为 Word(alphas, alphanums + "-,./_:*+=#[];")
- 您可能需要重新考虑是否要允许“=”作为
token
的一部分。如果有人在 token
和定界符“=”之间省略了 space,那么本应作为定界符的内容将被吸收到 token
键中。
- 考虑添加结果名称以帮助您访问每个键值对的键和值位:
multilineString = Group(token("key") + equals + OneOrMore(stringTemplate + ~FollowedBy(equals))("value"))
。然后你可以像 match.key
和 match.value
一样访问它们 - 当然你可以只使用列表索引来获取密钥 match[0]
,但我发现命名访问更容易使用。
我正在使用 pyparser 并想解析包含树结构的文件,其值存储在等号之后,否则没有实际的分隔符。
除了极少数情况下数据存储在多行之外,我已经完成了所有解析,所以我必须重写解析器不要停止从等号到行尾但从等号获取值到另一个等号(或 end
),忽略前面的单词(或忽略 end
)。
数据示例:
(
ItemName = foo
SomeOtherStuff = bar
foo1
foo2
AString1 = ItemName
SomeOtherStuff
)
代码:
equals = Suppress("=")
token = Word(alphanums + "-,./_:*+=#[];")
decimal = Regex(r'-?0|[1-9]\d*').setParseAction(lambda t:int(t[0]))
stringTemplate = token | decimal
sexpList = Group(Suppress("(") + ZeroOrMore(sexp) + Suppress(")"))
sexp = Forward()
这显然行不通
astring = Group(stringTemplate + equals + stringTemplate)
所以我试过这些:
multilineString = Group(token + equals + OneOrMore(stringTemplate) + ~FollowedBy(stringTemplate + equals))
multilineString = Group(token + equals + OneOrMore(stringTemplate) + NotAny(stringTemplate + equals))
multilineString = Group(token + equals + OneOrMore(stringTemplate) + ~(stringTemplate + equals))
但是没有用。我得到的要么是错误,要么是解析器将所有数据吞噬为一条记录。
您在 ~FollowedBy
的正确轨道上,但这些表达式必须是 OneOrMore
重复表达式的一部分。类似于:
multilineString = Group(token + equals + OneOrMore(stringTemplate + ~FollowedBy(equals)))
for match in multilineString.searchString(test):
match.pprint()
其他一些评论:
- 查看
token
、decimal
和stringTemplate
的定义。就目前而言,您永远不会匹配decimal
表达式。为避免将integer
误认为token
,我建议您将token
更改为Word(alphas, alphanums + "-,./_:*+=#[];")
- 您可能需要重新考虑是否要允许“=”作为
token
的一部分。如果有人在token
和定界符“=”之间省略了 space,那么本应作为定界符的内容将被吸收到token
键中。 - 考虑添加结果名称以帮助您访问每个键值对的键和值位:
multilineString = Group(token("key") + equals + OneOrMore(stringTemplate + ~FollowedBy(equals))("value"))
。然后你可以像match.key
和match.value
一样访问它们 - 当然你可以只使用列表索引来获取密钥match[0]
,但我发现命名访问更容易使用。