s/// en Python dans les scripts

Le
Tribulations Parallèles
Bonjour à tous,

Je me mets à Python; connaissant un peu Perl et les outils traditionnels
Unix (sed, awk, expressions régulières), je me demande comment écrire en
Python ce genre de bout de code extrait de l'un de mes programmes (voir
ci-dessous). Le code permet de faire un "edit in place" du fichier
$path/$name/$name.lyx sans passer par un fichier temporaire, et d'utiliser
l'opérateur de substitution s/// de manière simple sur le fichier.

Comment réaliser une chose équivalente en Python, le plus simplement
possible?

Julien

= extrait de code
# cf http://www.unix.org.ua/orelly/perl/cookbook/ch07_10.htm
# local permet de changer la valeur locale (innermost block, eval, ou
# file) d'une variable déjà existante, ici des variables
# d'environnement. Ici on veut émuler le -i de Perl en ligne de
# commande.
local @ARGV = "$path/$name/$name.lyx";
local $^I = ''; # remplacer par ".orig" pour garder une
#copie du fichier temporaire.
while ( <> )
{
s/Auteur(s) - Titre/$author - $title/;
s/auteur_coucou/$author_name/;
s/Fey01/$label/;
print;
}
=



--
"Allez, Monsieur, allez, et la foi vous viendra." (D'Alembert).
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Bruno Desthuilliers
Le #589454
Bonjour à tous,

Je me mets à Python; connaissant un peu Perl et les outils traditionnels
Unix (sed, awk, expressions régulières), je me demande comment écrire en
Python ce genre de bout de code extrait de l'un de mes programmes (voir
ci-dessous). Le code permet de faire un "edit in place" du fichier
$path/$name/$name.lyx sans passer par un fichier temporaire, et d'utiliser
l'opérateur de substitution s/// de manière simple sur le fichier.

Comment réaliser une chose équivalente en Python, le plus simplement
possible?


Je ne suis pas sûr que Python soit le meilleurs outil pour ce genre de
traitements. Pas ce que ce soit impossible, bien sûr, mais c'est AMHA
typiquement un job pour Perl.

Julien

==== extrait de code
# cf http://www.unix.org.ua/orelly/perl/cookbook/ch07_10.htm
# local permet de changer la valeur locale (innermost block, eval, ou
# file) d'une variable déjà existante, ici des variables
# d'environnement. Ici on veut émuler le -i de Perl en ligne de
# commande.
local @ARGV = "$path/$name/$name.lyx";
local $^I = ''; # remplacer par ".orig" pour garder une
#copie du fichier temporaire.
while ( <> )
{
s/Auteur(s) - Titre/$author - $title/;
s/auteur_coucou/$author_name/;
s/Fey01/$label/;
print;
}
=== >




William Dode
Le #589452
On 15-03-2007, Tribulations Parallèles wrote:
Bonjour à tous,

Je me mets à Python; connaissant un peu Perl et les outils traditionnels
Unix (sed, awk, expressions régulières), je me demande comment écrire en
Python ce genre de bout de code extrait de l'un de mes programmes (voir
ci-dessous). Le code permet de faire un "edit in place" du fichier
$path/$name/$name.lyx sans passer par un fichier temporaire, et d'utiliser
l'opérateur de substitution s/// de manière simple sur le fichier.

Comment réaliser une chose équivalente en Python, le plus simplement
possible?


Avec la méthode replace de string

machaine.replace("Auteur(s) - Titre", "%s - %s" % (auteur, titre))


Pour récupérer les variables d'environnement on utilise os.environ qui
est un dictionnaire. Ca pourrait donc donner

machaine.replace("Auteur(s) - Titre", "%(auteur)s - %(titre)s" % os.environ)



Julien

==== extrait de code
# cf http://www.unix.org.ua/orelly/perl/cookbook/ch07_10.htm
# local permet de changer la valeur locale (innermost block, eval, ou
# file) d'une variable déjà existante, ici des variables
# d'environnement. Ici on veut émuler le -i de Perl en ligne de
# commande.
local @ARGV = "$path/$name/$name.lyx";
local $^I = ''; # remplacer par ".orig" pour garder une
#copie du fichier temporaire.
while ( <> )
{
s/Auteur(s) - Titre/$author - $title/;
s/auteur_coucou/$author_name/;
s/Fey01/$label/;
print;
}
=== >





--
William Dodé - http://flibuste.net
Développeur informatique indépendant

Tribulations Parallèles
Le #589451
William Dode wrote:

Avec la méthode replace de string

machaine.replace("Auteur(s) - Titre", "%s - %s" % (auteur, titre))


Pour récupérer les variables d'environnement on utilise os.environ qui
est un dictionnaire. Ca pourrait donc donner

machaine.replace("Auteur(s) - Titre", "%(auteur)s - %(titre)s" %
os.environ)


Merci pour ta réponse; si je ne m'abuse, cela ne permet pas de faire
un "edit-in-place"?

Julien

--
"Allez, Monsieur, allez, et la foi vous viendra." (D'Alembert).

William Dode
Le #589447
On 15-03-2007, Tribulations Parallèles wrote:
William Dode wrote:

Avec la méthode replace de string

machaine.replace("Auteur(s) - Titre", "%s - %s" % (auteur, titre))


Pour récupérer les variables d'environnement on utilise os.environ qui
est un dictionnaire. Ca pourrait donc donner

machaine.replace("Auteur(s) - Titre", "%(auteur)s - %(titre)s" %
os.environ)


Merci pour ta réponse; si je ne m'abuse, cela ne permet pas de faire
un "edit-in-place"?


Non, il renvoi une nouvelle chaine (si c'est ce que tu veux dire par
edit-in-place ?)


--
William Dodé - http://flibuste.net
Développeur informatique indépendant


Tribulations Parallèles
Le #589446
William Dode wrote:

Non, il renvoi une nouvelle chaine (si c'est ce que tu veux dire par
edit-in-place ?)


En fait, par edit in place, je parle du "sed -i" ou du "perl -i" qui permet
de modifier un fichier sans passer par un fichier temporaire. Le code perl
que j'ai proposé dans le post initial permet de faire un edit in place à
partir d'un script (alors que perl -i s'utilise en ligne de commande). Donc
ma question est de savoir si je peux faire un edit in place à partir d'un
script python, sans passer par un fichier temporaire.
Dans ta solution, j'ai l'impression qu'on travaille sur une string, et qu'on
ne peut pas travailler sur un fichier directement. A moins qu'un fichier
puisse être considéré comme une string dans certaines conditions?

Julien

--
"Allez, Monsieur, allez, et la foi vous viendra." (D'Alembert).

Michel Claveau
Le #590481
Bonsoir !

je ne connais ni Perl, ni Sed.

Mais, si l'on remplace, dans un fichier, des chaînes par des chaînes
plus grande, on est obligé, soit de passer par un fichier temporaire,
soit de charger en mémoire le fichier entier, pour le récrire (à partir
de la première modif).





--
@-salutations

Michel Claveau
Sébastien Kirche
Le #590480
Le 15 mars 2007 à 22:13, Michel Claveau a formulé :

Bonsoir !

je ne connais ni Perl, ni Sed.

Mais, si l'on remplace, dans un fichier, des chaînes par des chaînes
plus grande, on est obligé, soit de passer par un fichier temporaire,
soit de charger en mémoire le fichier entier, pour le récrire (à
partir de la première modif).


Il me semble bien que l'option -i de sed (pour in-place) passe par un
fichier temporaire pour remplacer le fichier d'origine à la fin (c'est
logique). Je ne vois pas pourquoi perl ne ferait pas pareil.
--
Sébastien Kirche

Bruno Desthuilliers
Le #590479
William Dode wrote:


Non, il renvoi une nouvelle chaine (si c'est ce que tu veux dire par
edit-in-place ?)



En fait, par edit in place, je parle du "sed -i" ou du "perl -i" qui permet
de modifier un fichier sans passer par un fichier temporaire.


AMHA, ça passe par un fichier temporaire - difficile de faire autrement
si on ne travaille pas sur des champs binaires de taille fixe. Par
contre, ce fichier temporaire est géré par l'appli (interpréteur, ce que
tu veux), et c'est donc transparent pour l'utilisateur.

Et non, Python ne permet pas ça. Contrairement à Sed, Awk et Perl,
Python n'a pas été spécifiquement conçu pour ce genre d'opérations.


Maric Michaud
Le #591502
Pas vraiment pour répondre à la question, Bruno a déjà noté que python
n'était pas prévu pour s'intégrer directement aux shell.

Bruno Desthuilliers wrote:

AMHA, ça passe par un fichier temporaire - difficile de faire autrement
si on ne travaille pas sur des champs binaires de taille fixe.


sed passe par un fichier temporaire, c'est le principe, il travaille ligne à
ligne, et ne doit pas échouer si la mémoire ne peut contenir le fichier à
lire comme le résultat.

:~/temp$ echo toto > tata
:~/temp$ sed -i "s/o/i/g" tata
:~/temp$ cat tata
titi
:~/temp$ strace sed -i "s/o/i/g" tata | more
...
open("tata", O_RDONLY) = 3
...
open("./sedMH3MgX", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
...
rename("./sedMH3MgX", "tata") = 0
...

Perl fonctionne bien sur le même principe, il ouvre le fichier est ensuite
le supprime (par l'appel système unlink), utilisant de ce fait une
propriété de filesystems unix qui garantissent que tant qu'un descripteur
de fichier est ouvert le fichier n'est pas écrasé (pas du tout sûr que ça
fonctionne sous Windows).

:~/temp$ (strace perl -pi -e "s/o/a/g" tata 2>&1 )| grep tata
...
open("tata", O_RDONLY) = 3
unlink("tata") = 0
open("tata", O_WRONLY|O_CREAT|O_EXCL, 0666) = 4

donc l'équivalent python c'est rigoureusement :

:~/temp$ cat pysed
#!/usr/bin/env python
import os
from sys import argv

input = open(argv[3])
os.unlink(argv[3])
output = open(argv[3], 'w')

for i in input :
output.write(i.replace(argv[1], argv[2]))

:~/temp$ cat tata
tootoo
tootoo

:~/temp$ ./pysed oo i tata
:~/temp$ cat tata
titi
titi


_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097

Elby
Le #595748
Pour faire ce genre de manip typiquement perlienne, j'utilise le module
fileinput. J'ai retrouvé un script que j'avais fait pour nettoyer des
fichiers textes mal encodés, qui est un exemple assez simple
d'utilisation :

***************** clean_srt *************************
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-

"""
Petit script pour nettoyer des fichiers textes mal encodés

usage :
clean_srt *.srt
"""

from re import compile
import fileinput

# Dictionnaire contenant les symboles à remplacer
bad_char = {
'x92' : "'",
'x9c' : "oe",
}

# RE permettant de rechercher les symboles précédents
RE_bad_char = compile(r'[%s]' % ''.join(bad_char.keys()))

def get_good_char(m,good_charºd_char.get):
return good_char(m.group()[0])

# Utilisation du module fileinput pour faire des substitution
# à la volée en créant des fichiers de sauvegarde (.bak)
for line in fileinput.input(inplace=True, backup='.bak') :
print RE_bad_char.sub(get_good_char, line),


# vim: set et sts=4 ts=4:
********************************************************


L'intérêt du module fileinput est qu'il peut aussi être utilisé
avec des pipe, comme l'opérateur <> en perl :

cat old.srt | clean_srt > new.srt

--
Enjoy
Publicité
Poster une réponse
Anonyme