OVH Cloud OVH Cloud

search and replace avancé

5 réponses
Avatar
remi
Bonjour,

Dans un fichier texte, je souhaiterais remplacer tous les \url{adresse
web} par : <A HREF = "adresse web">adresse web</A>.
Une idée ? Une doc ?
Merci.
Rémi.

5 réponses

Avatar
Do Re Mi chel La Si Do
Bonsoir !


Regarde le module "re".


@-salutations
--
Michel Claveau
Avatar
remi
Bonsoir !


Regarde le module "re".


Oui justement... Bon, après plusieurs essais/erreurs, j'arrive au code
suivant qui, semble fonctionner, et qui dans un premier temps extrait du
fichier texte une partie précise et converti les url{adresse} en la
version HTML :

#----------
import re

file_in = open('faq_test.tex','r')
file_string = file_in.read()
file_in.close()

##########
# Extraction de la la partie du fichier entre begin{document} et
end{document}...
# ########

# la RE correspondante au corps du doc :

corps = r"""begin{document}(?P<contents>.*)end{document}"""
compile_obj = re.compile(corps, re.IGNORECASE| re.DOTALL)
match_obj = compile_obj.search(file_string)

# contents est la string avec la partie du fichier voulue

contents = match_obj.group('contents')

##########
# url{adresse} -> <A HREF = "adresse">adresse</A>
##########

url = r'url{(.*)}'
urlc = re.compile(url)

# on empile tous les contents de url{} dans une liste

url_list = re.findall(urlc, contents)

# on dépile...

nouveau = contents
lng=len(url_list)
i=1
while i <= lng:
texte = ('<A HREF = "%s">%s</A>' % (url_list[i-1],url_list[i-1]))
i=i+1
nouveau = re.sub(urlc,texte,nouveau,1)


print nouveau
#---------------

Est-ce pythonesque ? ;-)
si taht ceni ? ;-)
@+ et merci.
Rémi.

Avatar
Guillaume Bouchard
remi wrote:
file_in = open('faq_test.tex','r')
file_string = file_in.read()
file_in.close()


Sache que le mode par defaut est 'r', donc tu peux écrire sans problème:

file_in = open('faq_test.tex','r').read()

Pas besoin de fermer, python s'en occupe seul en voyant que l'objet file
n'est pas associé à une variable.

corps = r"""begin{document}(?P<contents>.*)end{document}"""
compile_obj = re.compile(corps, re.IGNORECASE| re.DOTALL)


re.I | re.S est equivalent.

match_obj = compile_obj.search(file_string)


Je dirais que là tu utilises une usine à gaz pour rien.

avec str.index tu recuperes la position d'un élément particulier dans
une chaine.

D'ou

start = r'begin{document}'
end = r'end{document}'
file_string = r"un document Latex begin{document}avec du
contenuend{document}"



file_string[file_string.index(start) +
len(start):file_string.index(end)]



'avec du contenu'


url = r'url{(.*)}'
urlc = re.compile(url)


Tu peux aussi le faire en une ligne.

url_list = re.findall(urlc, contents)

# on dépile...

nouveau = contents

lng=len(url_list)
i=1
while i <= lng:


Tu n'utiliseras JAMAIS cela en Python. Tu peux toujours boucler sur une
liste avec

for i in list:

Dans le cas où tu veuille la valeur et l'indice :

for i,value in enumerate(list):

print list[i] == value # TRUE

texte = ('<A HREF = "%s">%s</A>' % (url_list[i-1],url_list[i-1]))
i=i+1
nouveau = re.sub(urlc,texte,nouveau,1)


Ici non.

for i in urlc.findall(contents):
text = '...'
contents = urlc.sub(texte,contents,1)


Pourquoi ? urlc.findall est un iterateur, tu peux donc boucler dessus.
Note que cela marche avec enormement de chose (les lignes d'un fichier,
le contenu d'une liste)

urlc est un objet de type regex, il a donc les methodes de la classe re,
donc sub. Cela t'évite le re.sub(urlc...)

Note une chose HS, en html on ecrit les tags en minuscule.

Est-ce pythonesque ? ;-)


Pas encore :)
Apparament tu as des habitude de langage trés fonctionel où tu ne peux
faire qu'une chose par ligne. Perd cette habitude, Python te permet de
faire plus en moins de ligne et plus lisiblement. Je ne te dis pas qu'il
faut tous faire en 1 ligne, cela fait des trucs ignobles :

"%s@%s.%s" % tuple([i[::-1] for i in
"".replace('@','.').split('.')])



''

Mais je te dis juste que des fois, c'est plus propre et concis en une
ligne que 10.

--
Guillaume.



Avatar
remi
Bonjour,

Merci beaucoup pour vos remarques. Elles m'ont beaucoup apporté.
Pour info, voici le code "final" :

#--------------

import re
file_string = open('faq_test.tex').read()

##########
# Extraction de partie entre tableofcontents et end{document}...
# ########

start = r'tableofcontents'
end = r'end{document}'
contents = file_string[file_string.index(start) +
len(start):file_string.index(end)]

# ###
# url{adresse} -> <a href = "adresse">adresse</a>
# ###

urlc = re.compile(r'url{(.*)}')

for i in urlc.findall(contents):
text = ('<a href = "%s">%s</a>' % (i, i))
contents = urlc.sub(text,contents,1)

print contents
#-----------
C'est deux fois plus court qu'avant !



Est-ce pythonesque ? ;-)



Pas encore :)
Apparament tu as des habitude de langage trés fonctionel où tu ne peux
faire qu'une chose par ligne. Perd cette habitude, Python te permet de
faire plus en moins de ligne et plus lisiblement.


Je débute et n'ai _aucune_ expérience de prog (à part sur calculatrice
HP48, il y a bien longtemps...)

Merci ! :-)
@+
Rémi


Avatar
Guillaume Bouchard
remi wrote:
Bonjour,


Bonjour,

Merci beaucoup pour vos remarques. Elles m'ont beaucoup apporté.


De rien.

Je débute et n'ai _aucune_ expérience de prog (à part sur calculatrice
HP48, il y a bien longtemps...)


Hum. Juste une chose. Soit tu sais que tu ne feras jamais que du langage
de haut level come le python. Soit tu penses un jour faire du bas level
comme le C et je te conseil vraiment de commencer dans l'autre sens.

Je t'explique. Quand tu maitrises un langage comme le C, quand tu passes
à du haut level cela te simplifies le travail, mais tout ce que tu as
apprit n'est pas perdu, juste simplifié, tourné differament.

Dans l'autre sens, tu vas te retrouver avec un langage qui ne gere que
quelques types primaires alors que tu étais habitué à un langage avec
enormement de types existants. Tu va te retrouvé à devoir geré toi même
la mémoire alors que tu ignorais que cela doit bien se faire quelque
part. Bref AMHA ce sens est une grande galère.

--
Guillaume.