Python 无法使用pyparsing正确分析此文件

Python 无法使用pyparsing正确分析此文件,python,parsing,pyparsing,Python,Parsing,Pyparsing,我正在尝试使用惊人的python库pyparsing解析一个文件,但我遇到了很多问题 我试图解析的文件类似于: sectionOne: list: - XXitem - XXanotherItem key1: value1 product: milk release: now subSection: skey : sval slist: - XXitem mods: - XXone - XXtwo version: last s

我正在尝试使用惊人的python库
pyparsing
解析一个文件,但我遇到了很多问题

我试图解析的文件类似于:

sectionOne:
  list:
  - XXitem
  - XXanotherItem
  key1: value1
  product: milk
  release: now
  subSection:
    skey : sval
    slist:
    - XXitem
  mods:
  - XXone
  - XXtwo
  version: last
sectionTwo:
  base: base-0.1
  config: config-7.0-7
正如您所看到的,是一个缩进的配置文件,这或多或少就是我试图定义语法的方式

  • 该文件可以有一个或多个节
  • 每个节由节名称和节内容组成
  • 每个部分都有缩进的内容
  • 每个节内容可以有一对或多对键/值或一个子节
  • 每个值可以只是一个单词或一个项目列表
  • 项目列表是由一个或多个项目组成的组
  • 每个项目都是连字符+以“XX”开头的名称
我曾尝试使用pyparsing创建此语法,但没有成功

import pprint
import pyparsing
NEWLINE = pyparsing.LineEnd().suppress()
VALID_CHARACTERS = pyparsing.srange("[a-zA-Z0-9_\-\.]")
COLON = pyparsing.Suppress(pyparsing.Literal(":"))
HYPHEN = pyparsing.Suppress(pyparsing.Literal("-"))
XX = pyparsing.Literal("XX")

list_item = HYPHEN + pyparsing.Combine(XX + pyparsing.Word(VALID_CHARACTERS))
list_of_items = pyparsing.Group(pyparsing.OneOrMore(list_item))

key = pyparsing.Word(VALID_CHARACTERS) + COLON
pair_value = pyparsing.Word(VALID_CHARACTERS) + NEWLINE
value = (pair_value | list_of_items)

pair = pyparsing.Group(key + value)

indentStack = [1]

section = pyparsing.Forward()
section_name = pyparsing.Word(VALID_CHARACTERS) + COLON
section_value = pyparsing.OneOrMore(pair | section)
section_content = pyparsing.indentedBlock(section_value, indentStack, True)

section << pyparsing.Group(section_name + section_content)

parser = pyparsing.OneOrMore(section)

def main():
    try:
        with open('simple.info', 'r') as content_file:
            content = content_file.read()

            print "content:\n", content
            print "\n"
            result = parser.parseString(content)
            print "result1:\n", result
            print "len", len(result)

            pprint.pprint(result.asList())
    except pyparsing.ParseException, err:
        print err.line
        print " " * (err.column - 1) + "^"
        print err
    except pyparsing.ParseFatalException, err:
        print err.line
        print " " * (err.column - 1) + "^"
        print err


if __name__ == '__main__':
    main()
正如你所看到的,我有两个主要问题:

1.-每个节内容在列表中嵌套两次

2.-当密钥“版本”属于“sectionOne”时,将在“subSection”内对其进行解析

我的真正目标是能够获得python嵌套字典的结构,其中包含键和值,以便轻松提取每个字段的信息,但是
pyparsing.Dict
对我来说是一个模糊的东西

谁能帮帮我吗

提前谢谢


(很抱歉写了这么长的文章)

你真的非常接近了-恭喜,缩进解析器不是用pyparsing编写的最容易的

查看注释的更改。标有“A”的是修改,以解决您的两个问题。标记为“B”的添加Dict构造,以便您可以使用配置中的名称作为嵌套结构访问解析的数据

最大的罪魁祸首是
indentedBlock
为您做了一些额外的分组,这妨碍了Dict的名称-值关联。使用
解组
将其剥离,让Dict可以查看底层对

祝你好运

import pprint
import pyparsing
NEWLINE = pyparsing.LineEnd().suppress()
VALID_CHARACTERS = pyparsing.srange("[a-zA-Z0-9_\-\.]")
COLON = pyparsing.Suppress(pyparsing.Literal(":"))
HYPHEN = pyparsing.Suppress(pyparsing.Literal("-"))
XX = pyparsing.Literal("XX")

list_item = HYPHEN + pyparsing.Combine(XX + pyparsing.Word(VALID_CHARACTERS))
list_of_items = pyparsing.Group(pyparsing.OneOrMore(list_item))

key = pyparsing.Word(VALID_CHARACTERS) + COLON
pair_value = pyparsing.Word(VALID_CHARACTERS) + NEWLINE
value = (pair_value | list_of_items)

#~ A: pair = pyparsing.Group(key + value)
pair = (key + value)

indentStack = [1]

section = pyparsing.Forward()
section_name = pyparsing.Word(VALID_CHARACTERS) + COLON
#~ A: section_value = pyparsing.OneOrMore(pair | section)
section_value = (pair | section)

#~ B: section_content = pyparsing.indentedBlock(section_value, indentStack, True)
section_content = pyparsing.Dict(pyparsing.ungroup(pyparsing.indentedBlock(section_value, indentStack, True)))

#~ A: section << Group(section_name + section_content)
section << (section_name + section_content)

#~ B: parser = pyparsing.OneOrMore(section)
parser = pyparsing.Dict(pyparsing.OneOrMore(pyparsing.Group(section)))
要显示Dict层次结构,请执行以下操作:

[['sectionOne', ['list', ['XXitem', 'XXanotherItem']], ... etc. ...
- sectionOne: [['list', ['XXitem', 'XXanotherItem']], ... etc. ...
  - key1: value1
  - list: ['XXitem', 'XXanotherItem']
  - mods: ['XXone', 'XXtwo']
  - product: milk
  - release: now
  - subSection: [['skey', 'sval'], ['slist', ['XXitem']]]
    - skey: sval
    - slist: ['XXitem']
  - version: last
- sectionTwo: [['base', 'base-0.1'], ['config', 'config-7.0-7']]
  - base: base-0.1
  - config: config-7.0-7
允许您编写如下语句:

print (result.sectionTwo.base)

您的配置格式看起来像YAML。你不能用“手工”来代替解析吗?谢谢你的评论@NikitaNemkin。是的,我可以使用PyYAM,事实上这就是我们现在正在使用的,但是我必须解析的文件来自一个涉众,他们倾向于引入一些小的修改,所以我们想开发一些内部解析器,以便能够相应地修改它,感谢您的快速响应。它现在工作得很好。你的图书馆很有趣,只是有点缺少文档。再次感谢,做得很好!
[['sectionOne', ['list', ['XXitem', 'XXanotherItem']], ... etc. ...
- sectionOne: [['list', ['XXitem', 'XXanotherItem']], ... etc. ...
  - key1: value1
  - list: ['XXitem', 'XXanotherItem']
  - mods: ['XXone', 'XXtwo']
  - product: milk
  - release: now
  - subSection: [['skey', 'sval'], ['slist', ['XXitem']]]
    - skey: sval
    - slist: ['XXitem']
  - version: last
- sectionTwo: [['base', 'base-0.1'], ['config', 'config-7.0-7']]
  - base: base-0.1
  - config: config-7.0-7
print (result.sectionTwo.base)