2017-07-13 3 views
2

i essayer d'analyser la structure suivante à l'aide pyparsing:JSON Parsing comme la structure avec pyparsing

{ 
    firewall { 
     group { 
      address-group { 
       address 1.2.3.4 
      } 
      address-group { 
       address 5.6.7.4 
      } 
     } 
    } 
} 
Code

:

from pyparsing import * 

LBRACE, RBRACE = map(Suppress, "{}") 

prop = Word(printables, excludeChars="{}\"") 
numberValue = pyparsing_common.number() 

configObject = Forward() 
value = Forward() 
value << (prop | numberValue | Group(configObject)) 
memberDef = Group(prop + value) 
configMembers = delimitedList(memberDef) 
configObject << Dict(LBRACE + Optional(configMembers) + RBRACE) 

if __name__ == "__main__": 
    testdata = """ 
    { 
     firewall { 
      group { 
       address-group { 
        address 1.2.3.4 
       } 
       address-group { 
        address 1.2.3.4 
       } 
      } 
     } 
    } 
    """ 


results = configObject.parseString(testdata) 

print(results.firewall.group) 

Il jette

pyparsing.ParseException: attendu "}" (à l'équation 15), (ligne 3, colonne 9)

Si je ne dispose que d'un seul address-group il travaille:

{ 
    firewall { 
     group { 
      address-group { 
       address 1.2.3.4 
      } 
     } 
    } 
} 

EDIT:

{ 
    firewall { 
     group { 
      address-group { 
       address 1.2.3.4 
      } 
      address-group { 
       address 5.6.7.4 
      } 
     } 
    } 
} 

est résolu à l'aide configMembers = OneOrMore(memberDef) au lieu de configMembers = delimitedList(memberDef) je dois analyser cela aussi (notez le name après adress-group:

{ 
    firewall { 
     group { 
      address-group name1 { 
       address 1.2.3.4 
      } 
      address-group name2 { 
       address 5.6.7.4 
      } 
     } 
    } 
} 
+1

@BoswellGathu était sur la bonne voie . L'ajout d'une virgule contourne le bogue dans votre analyseur lorsque vous utilisez 'delimitedList' lorsque vous avez plusieurs entrées dans un objet. 'delimitedList' nécessite un délimiteur non-espace entre les entrées, la valeur par défaut étant une virgule. Si vous voulez juste avoir plusieurs valeurs sans délimiteurs, utilisez 'OneOrMore' ou' ZeroOrMore'. (Le prochain problème que vous aurez est que vous avez des clés en double, donc un seul apparaîtra dans votre Dict.) – PaulMcG

+0

@PaulMcG son travail en utilisant 'OneOrMore' mais comme vous l'avez mentionné, c'est un problème avec les clés dubliquées. Je pourrais également exporter la config avec des noms après chaque 'groupe-adresse' comme' nom-groupe d'adresses {... 'mais je ne sais pas comment analyser cela. (Nouveau dans l'analyse syntaxique) –

+0

Que diriez-vous de: 'address-group {nom1 1.2.3.4 nom2 5.6.7.8}'? Je suis assez sûr que cela va analyser votre analyseur actuel. – PaulMcG

Répondre

1

J'ai ajouté une virgule entre les deux groupes d'adresses et tout fonctionne

{ 
firewall { 
    group { 
     address-group { 
      address 1.2.3.4 
     }, 
     address-group { 
      address 5.6.7.4 
     } 
    } 
} 
} 

Le code est donc

from pyparsing import * 

LBRACE, RBRACE = map(Suppress, "{}") 

prop = Word(printables, excludeChars="{}\"") 
numberValue = pyparsing_common.number() 

configObject = Forward() 
value = Forward() 
value << (prop | numberValue | Group(configObject)) 
memberDef = Group(prop + value) 
configMembers = delimitedList(memberDef) 
configObject << Dict(LBRACE + Optional(configMembers) + RBRACE) 

if __name__ == "__main__": 
    testdata = """ 
    { 
     firewall { 
      group { 
       address-group { 
        address 1.2.3.4 
       }, 
       address-group { 
        address 5.6.7.4 
       } 
      } 
     } 
    } 
    """ 


results = configObject.parseString(testdata) 

print(results.firewall.group) 

et la sortie est

[['address-group', [['address', '1.2.3.4']]], ['address-group', [['address', 
'5.6.7.4']]]] 
+0

Si l'OP pouvait changer le format de l'entrée, il aurait simplement utilisé JSON au lieu de quelque chose qui nécessitait un analyseur personnalisé. – jwodder

+0

@jwodder this. Ce n'est pas un json :) –