2011-08-12 20 views
5

Estoy tratando de analizar una línea con pyparsing. Esta línea se compone de varios (clave, valores). Lo que me gustaría obtener es una lista de (clave, valores). Un ejemplo sencillo:Análisis no codicioso con pyparsing

ids = 12 fields = name 

debería desembocar en algo como: [('ids', '12'), ('fields', 'name')]

Un ejemplo más complejo:

ids = 12, 13, 14 fields = name, title 

debería desembocar en algo como: [('ids', '12, 13, 14'), ('fields', 'name, title')]

PS: la tupla en el interior la lista resultante es solo un ejemplo. Podría ser un dict u otra lista o lo que sea, no es tan importante.

Pero lo que yo he intentado hasta ahora obtener resultados como: [('ids', '12 fields')]

Pyparsing está comiendo la clave siguiente, teniendo en cuenta que también es parte del valor.

Aquí es un ejemplo de código:

import pyparsing as P 

key = P.oneOf("ids fields") 
equal = P.Literal('=') 
key_equal = key + equal 
val = ~key_equal + P.Word(P.alphanums+', ') 

gr = P.Group(key_equal+val) 
print gr.parseString("ids = 12 fields = name") 

Alguien me puede ayudar? Gracias.

Respuesta

7

El primer problema radica en esta línea:

val = ~key_equal + P.Word(P.alphanums+', ') 

Sugiere que la parte coincide con cualquier secuencia alfanumérica, seguido por el literal ', ', sino que coincide con cualquier secuencia de caracteres alfanuméricos, ',' y ' '.

Lo que se desea en su lugar es:

val = ~key_equal + P.delimitedList(P.Word(P.alphanums), ", ", combine=True) 

El segundo problema es que sólo se PARSE un valor de par de claves:

gr = P.Group(key_equal+val) 

lugar, se debe analizar el mayor número posible:

gr = P.Group(P.OneOrMore(key_equal+val)) 

Así que la solución correcta es:

>>> import pyparsing as P 
>>> key = P.oneOf("ids fields") 
>>> equal = P.Literal('=') 
>>> key_equal = key + equal 
>>> val = ~key_equal + P.delimitedList(P.Word(P.alphanums), ", ", combine=True) 
>>> gr = P.OneOrMore(P.Group(key_equal+val)) 
>>> print gr.parseString("ids = 12, 13, 14 fields = name, title") 
[['ids', '=', '12, 13, 14'], ['fields', '=', 'name, title']] 
+0

PD: editó ligeramente su publicación. Obtuve un mejor resultado con su solución. El problema es que solo obtengo la primera parte y no las siguientes partes. Obtengo [('ids', '12, 13,14 ')]. Me gustaría obtener [('ids', '12, 13,14 '), (' fields ',' name, title ')] – Oli

+0

@Oli: gracias por la captura. Agregué la solución a tu segundo problema. – blubb

+0

Muchas gracias. Exactamente lo que necesito – Oli

Cuestiones relacionadas