簡體   English   中英

無法使用pyparsing正確解析此文件

[英]Cannot parse correctly this file with pyparsing

我正在嘗試使用驚人的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()

結果是:

result1:
  [['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']]]]]
  len 2
  [
     ['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']
     ]]
     ]
  ]

如您所見,我有兩個主要問題:

1.-每個部分的內容兩次嵌套到一個列表中

2-當鍵“版本”屬於“ sectionOne”時,將在“ subSection”內部進行解析

真正的目標是能夠獲得具有鍵和值的python嵌套詞典的結構,以輕松提取每個字段的信息,但是pyparsing.Dict對我來說還是有些晦澀。

有人可以幫我嗎?

提前致謝

(很長的帖子對不起)

您確實非常接近-恭喜,縮進解析器並不是使用pyparsing編寫最容易的方法。

查看評論的更改。 標有“ A”的是為了解決上述兩個問題而進行的更改。 標有“ B”的代碼將添加Dict構造,以便您可以使用配置中的名稱以嵌套結構的形式訪問解析的數據。

最大的罪魁禍首是indentedBlock做一些額外的Group'ing對你來說,這在詞典的名稱值協會的方式獲得。 使用ungroup將其剝離,Dict可以看到底層對。

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)

#~ 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)))

現在可以代替pprint(result.asList())編寫:

print (result.dump())

顯示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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM