Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[Regexp] Besoin d'aide pour une substitution

6 réponses
Avatar
Kobayashi
Bonjour,

Je suis en train d'écrire un convertisseur
Makefile.am en CMakeLists.txt (il en existe
un chez kde mais écrit en ruby et qui ne
fait pas tout ce que je veux) ... et j'ai
besoin de remplacer la chaîne de caractères

"BLABLA$(TOTO)HIHIHI$(SSSS)TTTT"
par
"BLABLA${TOTO}HIHIHI${SSSS}TTTT"

en vrai, c'est
"add_subdirectory($(IDLDIR))"
par
"add_subdirectory(${IDLDIR})"

où l'on voit qu'il y a des doubles
parenthèses fermantes dans la chaîne
initiale.

Et, je nage un peu ... n'étant pas,
comment dire, à la pointe en expression
régulière.

Si quelqu'un a une idée, je suis preneur.

K.

6 réponses

Avatar
JB
Kobayashi a écrit :

"BLABLA$(TOTO)HIHIHI$(SSSS)TTTT"
par
"BLABLA${TOTO}HIHIHI${SSSS}TTTT"

en vrai, c'est
"add_subdirectory($(IDLDIR))"
par
"add_subdirectory(${IDLDIR})"




bonjour,

la regexp :

add_subdirectory($((w+)))

te permet de matcher le texte a l'interieur des doubles parenthèses.
avec un re.findall ca devrait le faire

utilises le programme retest, tres pratique, pour faire tes essais




Julien
Avatar
Bruno Desthuilliers
Kobayashi a écrit :
Bonjour,

Je suis en train d'écrire un convertisseur
Makefile.am en CMakeLists.txt (il en existe
un chez kde mais écrit en ruby et qui ne
fait pas tout ce que je veux) ... et j'ai
besoin de remplacer la chaîne de caractères

"BLABLA$(TOTO)HIHIHI$(SSSS)TTTT"
par
"BLABLA${TOTO}HIHIHI${SSSS}TTTT"

en vrai, c'est
"add_subdirectory($(IDLDIR))"
par
"add_subdirectory(${IDLDIR})"

où l'on voit qu'il y a des doubles
parenthèses fermantes dans la chaîne
initiale.



D'abord, trouver l'expression qui retourne ce qui t'intéresses. Ici
(d'après tes exemples),
- c'est l'expression littérale '$('
- suivie d'une séquence de une ou plusieurs lettres majuscules quelconques
- suivie de l'expression littérale ')'

Ce qui s'écrit:

r"$([A-Z]+)"

Testons :
>>> import re
>>> samples = [
... ("BLABLA$(TOTO)HIHIHI$(SSSS)TTTT","BLABLA${TOTO}HIHIHI${SSSS}TTTT"),
... ("add_subdirectory($(IDLDIR))", "add_subdirectory(${IDLDIR})")
... ]
>>> def test(exp):
... for src, expected in samples:
... print re.findall(exp, src)
...
>>> test(r"$([A-Z]+)")
['$(TOTO)', '$(SSSS)']
['$(IDLDIR)']
>>>

Ok. Maintenant, on veut capturer ce qu'il y a entre '$(' et ')' pour
pouvoir le réinjecter dans la chaine de remplacement. Il suffit pour ça
de placer la partie centrale de l'expression (la séquence de une ou
plusieurs majuscules quelconques) dans un groupe:

r"$(([A-Z]+))"

Une référence (sous la forme '1') sur ce groupe est ensuite utilisée
dans la chaine de remplacement:

r"${1}"

Après, y a plus qu'à passer le tout à re.sub (ou mieux, compiler
l'expression et appeler sa method .sub) :

exp = re.compile(r"$(([A-Z]+))")
repl = r"${1}"

for src, expected in samples:
print "src : '%s'" % src
print "expected : '%s'" % expected
dest = exp.sub(repl, src)
print "dest : '%s'" % dest
assert dest == expected, "expected '%s' - got '%s'" % (expected,
dest)


Et, je nage un peu ... n'étant pas,
comment dire, à la pointe en expression
régulière.



Celle là n'est pas bien méchante.
Avatar
Kobayashi
Bruno Desthuilliers a écrit :
Kobayashi a écrit :
Bonjour,

Je suis en train d'écrire un convertisseur
Makefile.am en CMakeLists.txt (il en existe
un chez kde mais écrit en ruby et qui ne
fait pas tout ce que je veux) ... et j'ai
besoin de remplacer la chaîne de caractères

"BLABLA$(TOTO)HIHIHI$(SSSS)TTTT"
par
"BLABLA${TOTO}HIHIHI${SSSS}TTTT"

en vrai, c'est
"add_subdirectory($(IDLDIR))"
par
"add_subdirectory(${IDLDIR})"

où l'on voit qu'il y a des doubles
parenthèses fermantes dans la chaîne
initiale.



D'abord, trouver l'expression qui retourne ce qui t'intéresses. Ici
(d'après tes exemples),
- c'est l'expression littérale '$('
- suivie d'une séquence de une ou plusieurs lettres majuscules quelconques
- suivie de l'expression littérale ')'

Ce qui s'écrit:

r"$([A-Z]+)"

Testons :
>>> import re
>>> samples = [
... ("BLABLA$(TOTO)HIHIHI$(SSSS)TTTT","BLABLA${TOTO}HIHIHI${SSSS}TTTT"),
... ("add_subdirectory($(IDLDIR))", "add_subdirectory(${IDLDIR})")
... ]
>>> def test(exp):
... for src, expected in samples:
... print re.findall(exp, src)
...
>>> test(r"$([A-Z]+)")
['$(TOTO)', '$(SSSS)']
['$(IDLDIR)']
>>>

Ok. Maintenant, on veut capturer ce qu'il y a entre '$(' et ')' pour
pouvoir le réinjecter dans la chaine de remplacement. Il suffit pour ça
de placer la partie centrale de l'expression (la séquence de une ou
plusieurs majuscules quelconques) dans un groupe:

r"$(([A-Z]+))"

Une référence (sous la forme '1') sur ce groupe est ensuite utilisée
dans la chaine de remplacement:

r"${1}"

Après, y a plus qu'à passer le tout à re.sub (ou mieux, compiler
l'expression et appeler sa method .sub) :

exp = re.compile(r"$(([A-Z]+))")
repl = r"${1}"

for src, expected in samples:
print "src : '%s'" % src
print "expected : '%s'" % expected
dest = exp.sub(repl, src)
print "dest : '%s'" % dest
assert dest == expected, "expected '%s' - got '%s'" % (expected, dest)


Et, je nage un peu ... n'étant pas,
comment dire, à la pointe en expression
régulière.



Celle là n'est pas bien méchante.



Merci beaucoup ! Je vais tester tout ça.

De mon côté, je me suis mis à me (re-)documenter
sur les "re" depuis 16h13 et, comme à chaque fois,
au début je me dis "c'est génial, comment peut-on
vivre sans !!" et puis après, petit à petit, je me
dis que ça génère du code difficile à maintenir ou
à partager avec d'autres développeurs ... et à chaque
fois, je laisse tomber pour tout faire en python pur !
Enfin, on va voir cette fois là !
Avatar
Bruno Desthuilliers
Kobayashi a écrit :
(snip)

De mon côté, je me suis mis à me (re-)documenter
sur les "re" depuis 16h13 et, comme à chaque fois,
au début je me dis "c'est génial, comment peut-on
vivre sans !!" et puis après, petit à petit, je me
dis que ça génère du code difficile à maintenir ou
à partager avec d'autres développeurs ...




La source du "problème" est la même dans les deux cas: la lisibilité.
Ceci étant, ce n'est que potentiellement un problème ; c'est à dire que
ce n'est un problème que si tes expressions deviennent trop compliquées
- ce qui indique en général que ce n'est pas forcément l'outil adapté
dans cette situation particulière.

Dans ton cas - et si tu n'a pas de transformations d'un ordre de
complexité supérieur -, les expressions rationnelles semblent
parfaitement appropriées.
Avatar
Kobayashi
Bruno Desthuilliers a écrit :
Kobayashi a écrit :
(snip)

De mon côté, je me suis mis à me (re-)documenter
sur les "re" depuis 16h13 et, comme à chaque fois,
au début je me dis "c'est génial, comment peut-on
vivre sans !!" et puis après, petit à petit, je me
dis que ça génère du code difficile à maintenir ou
à partager avec d'autres développeurs ...




La source du "problème" est la même dans les deux cas: la lisibilité.
Ceci étant, ce n'est que potentiellement un problème ; c'est à dire que
ce n'est un problème que si tes expressions deviennent trop compliquées
- ce qui indique en général que ce n'est pas forcément l'outil adapté
dans cette situation particulière.

Dans ton cas - et si tu n'a pas de transformations d'un ordre de
complexité supérieur -, les expressions rationnelles semblent
parfaitement appropriées.



Oui pour celle ci, c'était parfait. Merci encore !

Je l'ai remise à ma sauce en utilisant re.VERBOSE
(que je ne connaissais même pas !) :

p = re.compile(r"""
[$][(] # a $ then a (
(?P<value> # open the group value
[^)]* # the group contain 0 or more non ) characters
) # close the group
[)] # a ) at the end
""", re.VERBOSE)

Je me suis dit que le groupe était composé
de caractères différent de ")".
Cela marche très bien, mais je m'aperçoit
tout d'un coup que cela ne traite pas le
cas des définitions imbriquées du type
"aaa $(AZ$(BBB)) fff" :

content = "aaa $(AZ$(BBB)) fff"
content = p.sub(r"${g<value>}", content)
print content

--> aaa ${AZ$(BBB}) fff

Pour ce cas précis, je pense que j'en aurais
surement pas besoin mais pour des

if AAA
if BBB
CMD1
else
CMD2
endif
else
CMD3
endif

qu'il faut transformer en

if(AAA)
if(BBB)
CMD1
else(BBB)
CMD2
endif(BBB)
else(AAA)
CMD3
endif(AAA)

en cmake, je crois qu'il va falloir faire
chauffer la doc.
Avatar
Bruno Desthuilliers
Kobayashi a écrit :
Bruno Desthuilliers a écrit :
Kobayashi a écrit :
(snip)

De mon côté, je me suis mis à me (re-)documenter
sur les "re" depuis 16h13 et, comme à chaque fois,
au début je me dis "c'est génial, comment peut-on
vivre sans !!" et puis après, petit à petit, je me
dis que ça génère du code difficile à maintenir ou
à partager avec d'autres développeurs ...




La source du "problème" est la même dans les deux cas: la lisibilité.
Ceci étant, ce n'est que potentiellement un problème ; c'est à dire
que ce n'est un problème que si tes expressions deviennent trop
compliquées - ce qui indique en général que ce n'est pas forcément
l'outil adapté dans cette situation particulière.

Dans ton cas - et si tu n'a pas de transformations d'un ordre de
complexité supérieur -, les expressions rationnelles semblent
parfaitement appropriées.



Oui pour celle ci, c'était parfait. Merci encore !

Je l'ai remise à ma sauce en utilisant re.VERBOSE
(que je ne connaissais même pas !) :

p = re.compile(r"""
[$][(] # a $ then a (
(?P<value> # open the group value
[^)]* # the group contain 0 or more non ) characters
) # close the group
[)] # a ) at the end
""", re.VERBOSE)

Je me suis dit que le groupe était composé
de caractères différent de ")".
Cela marche très bien, mais je m'aperçoit
tout d'un coup que cela ne traite pas le
cas des définitions imbriquées du type
"aaa $(AZ$(BBB)) fff" :



Non, et c'est la limite (pas assez bien) connue des systèmes
d'expressions rationnelles. La mauvaise nouvelle, c'est qu'=à ce stade,
il te faut une vraie grammaire et un vrai parseur. La bonne nouvelle,
c'est que les packages disponibles pour ce genre de choses ne manquent pas:

http://wiki.python.org/moin/LanguageParsing

content = "aaa $(AZ$(BBB)) fff"
content = p.sub(r"${g<value>}", content)
print content

--> aaa ${AZ$(BBB}) fff

Pour ce cas précis, je pense que j'en aurais
surement pas besoin mais pour des

if AAA
if BBB
CMD1
else
CMD2
endif
else
CMD3
endif

qu'il faut transformer en

if(AAA)
if(BBB)
CMD1
else(BBB)
CMD2
endif(BBB)
else(AAA)
CMD3
endif(AAA)

en cmake, je crois qu'il va falloir faire
chauffer la doc.



Même problème. A partir du moment où tu a une grammaire "récursive", tu
peux oublier les expressions rationnelles...