OVH Cloud OVH Cloud

inserer des caractères à une place bien précise dans un document

16 réponses
Avatar
philippe
Bonjour,

je ne connais pas grand chose à perl mais je pense que vous pourriez
résoudre mon problème.

je dois modifier un fichier texte pour incorporer des donnees dans une base
de données.

il y a 100000 lignes d'où la nécessité d'un script.

il faut creer une copie d'un document texte.txt et y rajouter des 'simple
quotes' (en dessous du 4) :
- après la 4eme virgule,
- avant la 5eme virgule,
- apres la 13eme virgule,
- avant la 14eme virgule.

Votre aide serait grandement appréciée

d'avance merci

Philippe

6 réponses

1 2
Avatar
philippe
Jérémy JUST wrote:

On Sun, 26 Dec 2004 15:07:53 +0100
philippe wrote:

$t[4]| | =| qq{'$t[4]}| | ;
^ ^ ^ ^ ^

Tu as des caractères bizarres ici. Je pense que c'est un problème ce
copier-coller.


auriez vous une petite idée ?


D'autre part:
- tu n'avais pas précisé (ou bien j'avais mal lu) qu'il fallait faire
ça sur chaque ligne du texte (moi, je l'ai justement fait sur le texte
global),
- j'avais fait une grosse erreur de logique. :(


La version corrigée (cette fois-ci, je l'ai testée et elle semble
fonctionner) est:

<<<<<
#!/usr/bin/perl

open(TEXT, 'test2.txt') or die "Cannot open: $!n" ;

while(<TEXT>)
{my @t = split ',', $_ ;

$t[4] = qq{'$t[4]'} ;
$t[13] = qq{'$t[13]'} ;

print STDOUT join ',', @t ;
}











Merci Benoit et Jérémy,

vous me sortez une belle épine du pied!


en effet j'avais fait un copier-coller dans vi et ces pipes sont apparus en
bleu très foncé et je ne les avais pas vu

serait-ce trop demander comment faire pour remplacer deux virgules qui se
suivent par ,une_variable,
ex :
a,z,e,r,,y,u devient a,z,e,r,tttt,y,u
tttt etant la valeur de la variable.

d'avance un très grand merci

Philippe






Avatar
Benoit Izac
Bonjour,

le 27/12/2004 à 21:00, philippe a écrit
dans le message <cqppk4$m1o$ :

serait-ce trop demander comment faire pour remplacer deux virgules qui
se suivent par ,une_variable,
ex :
a,z,e,r,,y,u devient a,z,e,r,tttt,y,u
tttt etant la valeur de la variable.


$var='tttt'
s/,,/,$var,/

ou éventuellement (si tu peux avoir à faire plusieurs remplacements sur
une même ligne) :

while (s/,,/,$var,/g) {}

--
Benoit Izac

Avatar
Jérémy JUST
On Mon, 27 Dec 2004 22:08:09 +0100
Benoit Izac wrote:

$var='tttt'
s/,,/,$var,/


Oui, mais dans les programmes que nous avons donnés, nous retirons les
virgules avant de traiter la chaîne (en la convertissant en tableau), et
nous les remettons après.
Donc il faut préciser à quel moment faire la substitution.

<<<<<
#!/usr/bin/perl

my $var = 'tttt' ;

open(TEXT, 'test2.txt') or die "Cannot open: $!n" ;

while(<TEXT>)
{s/,,/,$var,/g ; # Substitution avant découpage

my @t = split ',', $_ ;

$t[4] = qq{'$t[4]'} ;
$t[13] = qq{'$t[13]'} ;

print STDOUT join ',', @t ;
}








Une autre solution, que je trouve plus explicite, bien que plus
compliquée pour un débutant, est:

<<<<<
#!/usr/bin/perl

my $var = 'tttt' ;

open(TEXT, 'test2.txt') or die "Cannot open: $!n" ;

while(<TEXT>)
{my @t = split ',', $_ ;

# `map' prend chaque élément de la liste @t, le met dans $_
# et lui applique le code contenu dans le bloc {...}.
# Ici, ce code renvoie $var si $_ est égal à la chaîne vide,
# ou renvoie $_ autrement.
@t = map {($_ eq '') ? $var : $_} @t ;

$t[4] = qq{'$t[4]'} ;
$t[13] = qq{'$t[13]'} ;

print STDOUT join ',', @t ;
}







Comme pour le premier post, ces deux solutions viennent à l'esprit
suivant que l'on raisonne en terme de virgules ou d'éléments. Dans la
première solution, on travaille sur des successions de virgules, ce qui
n'est pas très intuitif. Dans la seconde solution, on cherche les
éléments vides dans la liste.


ou éventuellement (si tu peux avoir à faire plusieurs remplacements
sur une même ligne) :

while (s/,,/,$var,/g) {}


Avec l'option g, l'opérateur s remplace déjà toutes les occurrences du
motif. Donc le while est inutile.


--
Jérémy JUST





Avatar
Benoit Izac
Bonjour,

le 27/12/2004 à 23:20, Jérémy JUST a écrit
dans le message :

ou éventuellement (si tu peux avoir à faire plusieurs remplacements
sur une même ligne) :

while (s/,,/,$var,/g) {}


Avec l'option g, l'opérateur s remplace déjà toutes les occurrences
du motif. Donc le while est inutile.


% echo '1,2,,4,,,7,,,,0' | perl -lpe 's/,,/,_,/g'
1,2,_,4,_,,7,_,,_,0
% echo '1,2,,4,,,7,,,,0' | perl -lpe 'while (s/,,/,_,/g) {}'
1,2,_,4,_,_,7,_,_,_,0

--
Benoit Izac


Avatar
Benoit Izac
Dans le message ,

ou éventuellement (si tu peux avoir à faire plusieurs remplacements
sur une même ligne) :

while (s/,,/,$var,/g) {}


Avec l'option g, l'opérateur s remplace déjà toutes les occurrences
du motif. Donc le while est inutile.


% echo '1,2,,4,,,7,,,,0' | perl -lpe 's/,,/,_,/g'
1,2,_,4,_,,7,_,,_,0
% echo '1,2,,4,,,7,,,,0' | perl -lpe 'while (s/,,/,_,/g) {}'
1,2,_,4,_,_,7,_,_,_,0


D'ailleurs, la meilleure solution reste de faire un « look-ahead » :
% echo '1,2,,4,,,7,,,,0' | perl -pe 's/,(?=,)/,_/g'
1,2,_,4,_,_,7,_,_,_,0

voir aussi (s'il peut y avoir des blancs) :
s/,s*(?=,)/,_/g

--
Benoit Izac



Avatar
Jérémy JUST
Tu t'es déjà répondu à toi-même, mais je poste quand même la réponse
que j'avais préparée ce matin (je n'ai pas [et ne veux pas] d'accès aux
news en écriture depuis le boulot).


On Tue, 28 Dec 2004 00:23:50 +0100
Benoit Izac wrote:

Avec l'option g, l'opérateur s remplace déjà toutes les occurrences
du motif. Donc le while est inutile.


% echo '1,2,,4,,,7,,,,0' | perl -lpe 's/,,/,_,/g'
1,2,_,4,_,,7,_,,_,0
% echo '1,2,,4,,,7,,,,0' | perl -lpe 'while (s/,,/,_,/g) {}'
1,2,_,4,_,_,7,_,_,_,0


Il suffit de ne pas reconnaître plus que nécessaire (là,
effectivement, les occurrences se marchaient dessus). Pour ça, je
propose de vérifier l'existence de la seconde virgule sans la
reconnaître véritablement, avec une assertion de longueur nulle:

$ echo '1,2,,4,,,7,,,,0' | perl -lpe 's/,(?=,)/,_/g'
1,2,_,4,_,_,7,_,_,_,0


M'enfin, je persiste à penser que voir une telle ligne comme « une
successions de virgules avec des choses entre elles » est beaucoup moins
intuitif qu'« une succession de champs séparés par des virgules ».

--
Jérémy JUST


1 2