OVH Cloud OVH Cloud

Besoin d'aide pour utiliser pyparsing

6 réponses
Avatar
Sébastien Ramage
Bonjour =E0 tous,
je rencontre un petit probl=E8me =E0 l'utilisation de pyparsing.
je souhaite parser un fichier texte ressemblant =E0 ceci :

var1 =3D 12;
var2 =3D "4.0";
var3 =3D "text";
"test" =3D 14;
var4 =3D "test "special test";

j'ai donc fait le script ci-dessous :

from pyparsing import *

t_PV =3D Literal(';').suppress()
t_EQUAL =3D Literal('=3D').suppress()

t_nom =3D Word(alphas,alphas+nums)
t_entier =3D Word(nums)
t_chaine =3D Combine(Literal('"') + Word(printables) + Literal('"'))

t_valeur =3D t_nom | t_entier | t_chaine
t_var =3D t_nom | t_chaine
t_aff =3D Group(t_var + t_EQUAL + t_valeur + t_PV)
test =3D ZeroOrMore(t_aff)

chaine_de_test =3D """
var1 =3D 12;
var2 =3D "4.0";
var3 =3D "text";
"test" =3D 14;
var4 =3D "test "special test";
"""

r =3D test.parseString(chaine_de_test)
print r


Le probl=E8me qui se pose concerne la r=E9cup=E9ration des valeurs de type
chaine.
Elles sont d=E9limit=E9s par des " mais le probl=E8me c'est qu'il peut y
avoir des " dans la chaine elle m=EAme comme le montre la ligne var4 de
mon exemple.

Comment modifier la d=E9claration pour pyparsing r=E9cup=E8re bien ma
chaine?
j'ai fait plusieurs essais sans r=E9sultat concluant.

Merci d'avance pour votre aide

S=E9bastien

6 réponses

Avatar
Laurent Pointal
Bonjour à tous,
je rencontre un petit problème à l'utilisation de pyparsing.
<zip>


Le problème qui se pose concerne la récupération des valeurs de type
chaine.
Elles sont délimités par des " mais le problème c'est qu'il peut y
avoir des " dans la chaine elle même comme le montre la ligne var4 de
mon exemple.

Comment modifier la déclaration pour pyparsing récupère bien ma
chaine?
j'ai fait plusieurs essais sans résultat concluant.


Dans pyparsing il y a un quotedString qui est défini... ça devrais
résoudre ton problème (il y en a d'autres du genre dblQuotedString et
sqlQuotedString - de mémoire).

C'est une superbe librairie, mais pour bien comprendre et utiliser, il
faut se plonger dans les exemples (je viens juste de trouver que pour
Combine() il faut concaténer les arguments, et non les séparer par des
virgules... )


Merci d'avance pour votre aide

Sébastien



Cf les sites qui ont intégré pyparsing et qui ont généré la doc en
ligne, du genre:
http://code.enthought.com/ets/doc/api_docs/enthought.mathtext.pyparsing.html
Et autres sites... du genre:
http://www.geocities.com/ptmcg/python/howtousepyparsing.html


A+

Laurent.

Avatar
Jerome
Sébastien Ramage wrote:
Bonjour à tous,
je rencontre un petit problème à l'utilisation de pyparsing.
je souhaite parser un fichier texte ressemblant à ceci :

var1 = 12;
var2 = "4.0";
var3 = "text";
"test" = 14;
var4 = "test "special test";

j'ai donc fait le script ci-dessous :

from pyparsing import *

t_PV = Literal(';').suppress()
t_EQUAL = Literal('=').suppress()

t_nom = Word(alphas,alphas+nums)
t_entier = Word(nums)
t_chaine = Combine(Literal('"') + Word(printables) + Literal('"'))

t_valeur = t_nom | t_entier | t_chaine
t_var = t_nom | t_chaine
t_aff = Group(t_var + t_EQUAL + t_valeur + t_PV)
test = ZeroOrMore(t_aff)

chaine_de_test = """
var1 = 12;
var2 = "4.0";
var3 = "text";
"test" = 14;
var4 = "test "special test";
"""

r = test.parseString(chaine_de_test)
print r


Le problème qui se pose concerne la récupération des valeurs de type
chaine.
Elles sont délimités par des " mais le problème c'est qu'il peut y
avoir des " dans la chaine elle même comme le montre la ligne var4 de
mon exemple.

Comment modifier la déclaration pour pyparsing récupère bien ma
chaine?
j'ai fait plusieurs essais sans résultat concluant.

Merci d'avance pour votre aide

Sébastien



Ca tombe bien je m'y suis mis ce matin :)

Donc déjà tu peux modifier cela pour simplifier la lecture :

t_PV = Literal(';').suppress() => t_PV = Suppress(';')

Et après le problème vient de la variable t_chaine, tu peux faire 2 choses :

1/ faire comme python et autoriser des chaines avec des doubles ou des
simple quotes comme délimiteurs.
t_chaine = quotedString

auquel cas tu fais var4 = 'test " test' quand tu as besoin d'un "

2/ avec une expression régulière qui va chercher à faire par défaut "le
plus gros match" possible
t_chaine = Regex('".*"')


++

Avatar
Sébastien Ramage
On 20 fév, 15:55, Jerome wrote:
Sébastien Ramage wrote:
Bonjour à tous,
je rencontre un petit problème à l'utilisation de pyparsing.
je souhaite parser un fichier texte ressemblant à ceci :

var1 = 12;
var2 = "4.0";
var3 = "text";
"test" = 14;
var4 = "test "special test";

j'ai donc fait le script ci-dessous :

from pyparsing import *

t_PV = Literal(';').suppress()
t_EQUAL = Literal('=').suppress()

t_nom = Word(alphas,alphas+nums)
t_entier = Word(nums)
t_chaine = Combine(Literal('"') + Word(printables) + Literal('"'))

t_valeur = t_nom | t_entier | t_chaine
t_var = t_nom | t_chaine
t_aff = Group(t_var + t_EQUAL + t_valeur + t_PV)
test = ZeroOrMore(t_aff)

chaine_de_test = """
var1 = 12;
var2 = "4.0";
var3 = "text";
"test" = 14;
var4 = "test "special test";
"""

r = test.parseString(chaine_de_test)
print r

Le problème qui se pose concerne la récupération des valeurs de t ype
chaine.
Elles sont délimités par des " mais le problème c'est qu'il peut y
avoir des " dans la chaine elle même comme le montre la ligne var4 de
mon exemple.

Comment modifier la déclaration pour pyparsing récupère bien ma
chaine?
j'ai fait plusieurs essais sans résultat concluant.

Merci d'avance pour votre aide

Sébastien


Ca tombe bien je m'y suis mis ce matin :)

Donc déjà tu peux modifier cela pour simplifier la lecture :

t_PV = Literal(';').suppress() => t_PV = Suppress(';')

Et après le problème vient de la variable t_chaine, tu peux faire 2 c hoses :

1/ faire comme python et autoriser des chaines avec des doubles ou des
simple quotes comme délimiteurs.
t_chaine = quotedString

auquel cas tu fais var4 = 'test " test' quand tu as besoin d'un "

2/ avec une expression régulière qui va chercher à faire par défa ut "le
plus gros match" possible
t_chaine = Regex('".*"')

++- Masquer le texte des messages précédents -

- Afficher le texte des messages précédents -


Merci beaucoup pour votre aide, ça m'a éclairer un peu plus sur le
fonctionnement de pyparsing
mais je ne suis pas parvenu à résoudre mon problème car en plus des "
contenu dans la chaine, il y a aussi des retour à la ligne et
bizarrement si je les inclus pyparsing ne s'arrête pas à la fin de ma
chaine mais continu pour finalement me dire qu'il manque un ; à la
fin...

bref je me suis aperçu que les guillemets étaient systèmatiquement
précédés d'anti-slash " , j'ai essayé de les parser avec QuotedStr ing
mais impossible

je suis un peu déçu mais pour résoudre mon problème j'ai décidé de
faire un replace(r'"','') sur mon texte pour supprimer ces guillemets
qui m'encombrent

c'est bien dommage mais le fichier que je parse est bien plus complexe
que l'exemple que j'ai fournis donc je suis content d'en être arrivé

en fait la structure de mon fichier ressemble un peu à du xml avec de
nombreuses imbrications ce qui alourdi le parsing


Avatar
elGringo
On 21 fév, 08:22, "Sébastien Ramage"
wrote:
On 20 fév, 15:55, Jerome wrote:



Sébastien Ramage wrote:
Bonjour à tous,
je rencontre un petit problème à l'utilisation de pyparsing.
je souhaite parser un fichier texte ressemblant à ceci :

var1 = 12;
var2 = "4.0";
var3 = "text";
"test" = 14;
var4 = "test "special test";

j'ai donc fait le script ci-dessous :

from pyparsing import *

t_PV = Literal(';').suppress()
t_EQUAL = Literal('=').suppress()

t_nom = Word(alphas,alphas+nums)
t_entier = Word(nums)
t_chaine = Combine(Literal('"') + Word(printables) + Literal('"'))

t_valeur = t_nom | t_entier | t_chaine
t_var = t_nom | t_chaine
t_aff = Group(t_var + t_EQUAL + t_valeur + t_PV)
test = ZeroOrMore(t_aff)

chaine_de_test = """
var1 = 12;
var2 = "4.0";
var3 = "text";
"test" = 14;
var4 = "test "special test";
"""

r = test.parseString(chaine_de_test)
print r

Le problème qui se pose concerne la récupération des valeurs de type
chaine.
Elles sont délimités par des " mais le problème c'est qu'il peu t y
avoir des " dans la chaine elle même comme le montre la ligne var4 de
mon exemple.

Comment modifier la déclaration pour pyparsing récupère bien ma
chaine?
j'ai fait plusieurs essais sans résultat concluant.

Merci d'avance pour votre aide

Sébastien


Ca tombe bien je m'y suis mis ce matin :)

Donc déjà tu peux modifier cela pour simplifier la lecture :

t_PV = Literal(';').suppress() => t_PV = Suppress(';')

Et après le problème vient de la variable t_chaine, tu peux faire 2 choses :

1/ faire comme python et autoriser des chaines avec des doubles ou des
simple quotes comme délimiteurs.
t_chaine = quotedString

auquel cas tu fais var4 = 'test " test' quand tu as besoin d'un "

2/ avec une expression régulière qui va chercher à faire par dé faut "le
plus gros match" possible
t_chaine = Regex('".*"')

++- Masquer le texte des messages précédents -

- Afficher le texte des messages précédents -


Merci beaucoup pour votre aide, ça m'a éclairer un peu plus sur le
fonctionnement de pyparsing
mais je ne suis pas parvenu à résoudre mon problème car en plus des "
contenu dans la chaine, il y a aussi des retour à la ligne et
bizarrement si je les inclus pyparsing ne s'arrête pas à la fin de ma
chaine mais continu pour finalement me dire qu'il manque un ; à la
fin...

bref je me suis aperçu que les guillemets étaient systèmatiquement
précédés d'anti-slash " , j'ai essayé de les parser avec QuotedS tring
mais impossible

je suis un peu déçu mais pour résoudre mon problème j'ai décid é de
faire un replace(r'"','') sur mon texte pour supprimer ces guillemets
qui m'encombrent

c'est bien dommage mais le fichier que je parse est bien plus complexe
que l'exemple que j'ai fournis donc je suis content d'en être arrivé

en fait la structure de mon fichier ressemble un peu à du xml avec de
nombreuses imbrications ce qui alourdi le parsing


salut,
un truc simple comme ca te suffirait?:

f = open('test_parsing.txt').read().split('n')

__globals__ = globals()

for ligne in f:
cle, valeur = ligne.split('=')
#suppression des espaces superflues et du ; final
cle, valeur = cle.strip(), valeur.strip()[:-1]
if valeur.startswith('"'):
valeur = valeur.strip()[1:-1]
__globals__[cle] = valeur
continue
try:
valeur = float(valeur)
__globals__[cle] = valeur
continue
except:
pass
try:
valeur = int(valeur)
__globals__[cle] = valeur
continue
except:
pass
try:
valeur = tuple(valeur)
__globals__[cle] = valeur
continue
except:
pass
try:
valeur = dict(valeur)
__globals__[cle] = valeur
continue
except:
pass
try:
valeur = list(valeur)
__globals__[cle] = valeur
continue
except:
pass
__globals__[cle] = valeur


print var4
print var1 * 4



Avatar
Sébastien Ramage
salut,
un truc simple comme ca te suffirait?:



Merci pour ton aide, mais ton implémentation est beaucoup trop
simpliste pour mon application.
L'exemple que j'ai donné n'est là que pour illustrer les données
texte. Le fichier que je parse contient de nombreuses imbrications
avec des déclarations de tableau, des données binaires, de données
numérique bref suffisament compliqué pour rendre l'utilisation d'un
Parser obligatoire.

Avatar
chris
salut,
un truc simple comme ca te suffirait?:



Merci pour ton aide, mais ton implémentation est beaucoup trop
simpliste pour mon application.
L'exemple que j'ai donné n'est là que pour illustrer les données
texte. Le fichier que je parse contient de nombreuses imbrications
avec des déclarations de tableau, des données binaires, de données
numérique bref suffisament compliqué pour rendre l'utilisation d'un
Parser obligatoire.








Json est bien et avec pyparsing cela devient simple

http://pyparsing.wikispaces.com/space/showimage/jsonParser.py

A+
chris