OVH Cloud OVH Cloud

algorithme suppression commentaires

11 réponses
Avatar
R12y
Bonjour,

J'ai le code ci dessous qui est censé envoyer sur stdout (dans un premier
temps) les lignes d'un fichier passé en argument mais les lignes utiles,
sans commentairres ni lignes vides. Je n'arrive pas à "trouver la sortie",
car il ne fais pas ce que je veux qu'il fasse...

####################################
import sys, string
fichier_entree=open(sys.argv[1],"r")
lines_list=fichier_entree.readlines()

def clean_list (a_list):
if len(a_list)==1:
if (a_list[0] == '#') or (a_list[0] == ''):
# print ''
print "trouve long 1"
return None
else:
print a_list[0]
return None
else:
if (a_list[0] == '#') or (a_list[0] == ''):
print "trouve un comment"
clean_list (a_list[1:])
return None
else:
print a_list[0]
print "pas trouve comment"
clean_list (a_list[1:])
return None

clean_list (lines_list)
###################################################

Voici son execution.

mihamina-localhost>>>>./suppr_comment.py test.txt
l1

pas trouve comment
# c1

pas trouve comment
l2

pas trouve comment


pas trouve comment


pas trouve comment
# c2

pas trouve comment
l3

(En fait il me rajoute même une ligne vide à chaque fois...)

Voici le contenu du fichier de test:
mihamina-localhost>>>>cat test.txt
l1
# c1
l2


# c2
l3


Concernant le style, oui j'aime bien le style recursif/fonctionnel. ça m'a
séduit. J'espère gérer la plupart de ce que j'aurais à faire avec ce style,
si possible.

--
Un CMS Français à découvrir: CPS. (http://www.cps-project.org)
Hébergement gratuit de sites Zope, Plone, et CPS: http://www.objectis.org
Un lien qui peut servir:
http://www.google.fr/search?q=aspo+infogerance+serveur

10 réponses

1 2
Avatar
R12y
R12y wrote:

Bonjour,


[...]

if (a_list[0] == '#') or (a_list[0] == ''):


if ((a_list[0][0]=='#') or (a_list[0][0]=='')):
Puisqu'on regarde le premier element du premier element.

--
Un CMS Français à découvrir: CPS. (http://www.cps-project.org)
Hébergement gratuit de sites Zope, Plone, et CPS: http://www.objectis.org
Un lien qui peut servir:
http://www.google.fr/search?q=aspo+infogerance+serveur

Avatar
kaerbuhez
R12y wrote:


Bonjour,



[...]


if (a_list[0] == '#') or (a_list[0] == ''):



if ((a_list[0][0]=='#') or (a_list[0][0]=='')):
Puisqu'on regarde le premier element du premier element.

essaie :

print 'n'.join([li for li in a_list.split('n') if li!='' and li[0]!='#'])
Ca devrait fonctionner mais, bien que bien plus pythonesque à mon trés
humble avis, ça ne correspond sans doute pas à ... tes gouts
stylistiques. Ceci dit sans intention d'en polémiquer, chacun ses
critéres, moi c'est lisibilité, efficacité, ...

En espérant que ça aide (quelqu'un) ;-)


Avatar
Nicolas
Bonjour,

J'ai le code ci dessous qui est censé envoyer sur stdout (dans un premier
temps) les lignes d'un fichier passé en argument mais les lignes utiles,
sans commentairres ni lignes vides.


$ cat test.py
#! /usr/bin/env python

F = open("log.txt", "r")
for L in F.readlines():
if(L != "" and L != "rn" and L!="n" and L[0]!="#"):
print L,
F.close()

$ cat log.txt
#comment 1
#comment 2
ligne 1
ligne 2
#comment 3

#xyz
abc

$ python test.py
ligne 1
ligne 2
abc


(La virgule après le print L permet d'éviter le retour à la ligne
derrière print).

Nicolas.

Avatar
tiissa
R12y wrote:
R12y wrote:
if (a_list[0] == '#') or (a_list[0] == ''):


if ((a_list[0][0]=='#') or (a_list[0][0]=='')):
Puisqu'on regarde le premier element du premier element.


Il ne faut pas oublier que readlines() n'enlève pas le 'n' à la fin des
lignes.
Donc la deuxième condition ne sera jamais remplie dans ton texte et tu
garderas les lignes vides. Je te conseille plutôt :

if ((a_list[0][0]=='#') or (a_list[0][0]=='n')):

voire même simplement :

if a_list[0][0] in ('#', 'n'):

Ça explique d'ailleurs aussi les deux sauts de ligne que tu observes :
celui dans la ligne affichée et celui du print (du coup écrire plutôt
'print a_list[0],').


Une dernière remarque : tu écris deux fois la même chose (aux prints de
debug près).
Personnellement j'aurais fait le test sur une longueur nulle*. Ça permet
d'ailleurs de ne pas échouer (IndexError je suppose) sur un fichier vide.



* En fait j'aurais plutôt fait un for, un filter ou quelque chose dans
le genre. C'est important de connaître les différents styles
(paradigmes) de programmation ; c'est encore mieux de les utiliser à bon
escient.


Avatar
J.Pierre Pourrez
Le Thu, 11 Aug 2005 19:17:20 +0200, Nicolas a écrit :

Bonjour,

J'ai le code ci dessous qui est censé envoyer sur stdout (dans un
premier temps) les lignes d'un fichier passé en argument mais les
lignes utiles, sans commentairres ni lignes vides.


$ cat test.py
#! /usr/bin/env python

F = open("log.txt", "r")
for L in F.readlines():
if(L != "" and L != "rn" and L!="n" and L[0]!="#"):
print L,
F.close()

$ cat log.txt
#comment 1
#comment 2
ligne 1
ligne 2
#comment 3

#xyz
abc

$ python test.py
ligne 1
ligne 2
abc


(La virgule après le print L permet d'éviter le retour à la ligne
derrière print).

Nicolas.


Mieux vaut utiliser les expressions régulières :
#!/usr/bin/env python

import re

pattern1 = re.compile(r'(#| *$)')

f = open('log.txt')
buf = f.readlines()
f.close()
for ligne in filter(lambda x: pattern1.match(x) == None, buf):
print ligne,
print

Entre nous, c'est plus facile sans Python:
cat log.txt | sed '/^#/d; /^ *$/d'

Cordialement
Jean-Pierre


Avatar
Nicolas



Bonjour,

J'ai le code ci dessous qui est censé envoyer sur stdout (dans un
premier temps) les lignes d'un fichier passé en argument mais les
lignes utiles, sans commentairres ni lignes vides.




[...]

Mieux vaut utiliser les expressions régulières :
#!/usr/bin/env python

import re

pattern1 = re.compile(r'(#| *$)')
ou même pattern1 = re.compile(r'(#| t*$)')



f = open('log.txt')
buf = f.readlines()
f.close()
for ligne in filter(lambda x: pattern1.match(x) == None, buf):
print ligne,
print

Entre nous, c'est plus facile sans Python:
cat log.txt | sed '/^#/d; /^ *$/d'

Cordialement
Jean-Pierre


Bonjour,

J'ai peur que dans le cas d'un gros fichier, les expressions régulières
ne posent un problème de rapidité. Bien sûr, il ne s'agit pas là de
faire de l'optimisation prématurée, mais j'essaye d'éviter les
expressions régulières pour une tache aussi simple.
sed '/^#/d; /^ *$/d' log est plus rapide, sans surprise, mais la
différence entre le code avec ou sans regex est importante :

$ wc -l log
1520640 log

$ time sed '/^#/d; /^ *$/d' log > /dev/null
real 0m4.297s

$ time ./avec-if.py > /dev/null
real 0m3.563s

$ time ./avec-regex.py > /dev/null
real 0m6.828s

Sur un petit fichier, on ne verra pas la différence, mais sur plusieurs
millions de lignes, ou avec plusieurs scripts lancés simultanément, on y
perd.

Cordialement,
Nicolas.



Avatar
J.Pierre Pourrez
Le Fri, 12 Aug 2005 18:39:45 +0200, Nicolas a écrit :

J'ai peur que dans le cas d'un gros fichier, les expressions régulières
ne posent un problème de rapidité. Bien sûr, il ne s'agit pas là de
faire de l'optimisation prématurée, mais j'essaye d'éviter les
expressions régulières pour une tache aussi simple. sed '/^#/d; /^ *$/d'
log est plus rapide, sans surprise, mais la différence entre le code avec
ou sans regex est importante :

$ wc -l log
1520640 log

$ time sed '/^#/d; /^ *$/d' log > /dev/null real 0m4.297s

$ time ./avec-if.py > /dev/null
real 0m3.563s

$ time ./avec-regex.py > /dev/null
real 0m6.828s

Sur un petit fichier, on ne verra pas la différence, mais sur plusieurs
millions de lignes, ou avec plusieurs scripts lancés simultanément, on y
perd.


Merci pour les mesures.
Avec un bémol : votre script ne gère pas les lignes remplies d'espace.

Cela me conforte dans l'idée d'utiliser sed pour ce genre de tâches
même si j'aime bien Python

Je serais bien curieux de connaître les résultats avec Perl.

Cordialement
Jean-Pierre

Avatar
Nicolas


J'ai peur que dans le cas d'un gros fichier, les expressions régulières
ne posent un problème de rapidité. Bien sûr, il ne s'agit pas là de
faire de l'optimisation prématurée, mais j'essaye d'éviter les
expressions régulières pour une tache aussi simple. sed '/^#/d; /^ *$/d'
log est plus rapide, sans surprise, mais la différence entre le code avec
ou sans regex est importante :

$ wc -l log
1520640 log

$ time sed '/^#/d; /^ *$/d' log > /dev/null real 0m4.297s

$ time ./avec-if.py > /dev/null
real 0m3.563s

$ time ./avec-regex.py > /dev/null
real 0m6.828s

Sur un petit fichier, on ne verra pas la différence, mais sur plusieurs
millions de lignes, ou avec plusieurs scripts lancés simultanément, on y
perd.



Merci pour les mesures.
Avec un bémol : votre script ne gère pas les lignes remplies d'espace.


En effet.

Cela me conforte dans l'idée d'utiliser sed pour ce genre de tâches
même si j'aime bien Python

Je serais bien curieux de connaître les résultats avec Perl.



Je ne connais que très peu Perl, mais il me semble qu'une manière de le
faire pourrait être :

use IO::File;
my $in = new IO::File('<log');
while(<$in>){
my $L = $_;
if(not($L=~/^#/ or $L=~/^ *$/)){
print $L;
}
}

$ time perl comments.pl > /dev/null
real 0m2.297s

(1,5 Million de lignes quand même).
Ce qui est même plus rapide que tous les autres, mais un gourou de Perl
passera peut-être par là pour en faire une version d'une ligne et demi
encore plus rapide.

Nicolas.


Avatar
J.Pierre Pourrez
Le Fri, 12 Aug 2005 20:01:30 +0200, Nicolas a écrit :


Je ne connais que très peu Perl, mais il me semble qu'une manière de le
faire pourrait être :

use IO::File;
my $in = new IO::File('<log');
while(<$in>){
my $L = $_;
if(not($L=~/^#/ or $L=~/^ *$/)){


penser à utiliser unless à la place de if not

print $L;
}
}
}
$ time perl comments.pl > /dev/null
real 0m2.297s

(1,5 Million de lignes quand même).
Ce qui est même plus rapide que tous les autres, mais un gourou de Perl
passera peut-être par là pour en faire une version d'une ligne et demi
encore plus rapide.


Je ne suis pas un gourou de Perl mais ceci semble marcher :
cat log | perl -ne 'print unless (/^ *$/ || /^#/)'

Jean-Pierre

Avatar
ami
Les cas de figure sont nombreux : le meilleur moyen de supprimer les
commentaires est d'utiliser le module 'tokenize'. Et un excellent moyen
de comprendre tokenize est d'étudier le code de pyfuscate.
Ami
1 2