Bonjour,
J'ai un soucis de performance donc je cherche des solutions type awk voir perl.
Pour toutes les lignes commencant par ACT, je veux remplacer la valeur du champ 12 avec celle du champ 14 si la valeur du champ 12 commence par 0.
Pour l'instant j'ai une boucle qui prend toutes les lignes commencant par ACT et je teste si le champ 12 commence par zéro, si oui je fais un sed. Pour plus de performance, j'ai voulu contstruire un fichier avec les chaine sed de remplacement (s/ligne1/ligne2/g) pour exécuter un sed -f avec ce fichier en critère. Mais le sed avec fichier en critère ne fonctionne pas avec un gros fichier en critere.
La solution si elle existe serait de ne plus passer par un boucle.
exemple de ligne (séparateur = ~)
ENT~xxxxxx~20060101,000000~20060301,000000
ACT~xxxxxxxx~~xxxxxxxxxxx~xxxxxx~xxxxxxx~xxxxxx~x~xxxxxxxx~xxxxxx~x~0051~01~6020~01~~~0~~~294522~269824~0~~20060101,001500
ENA~xxxxxxxx~xxxxxx~20060101,001500~~0~20060101,004737~xxxxxxxxxxx~7~
ici sur la ligne ACT le champ 12 est 0051 il doit etre remplacé par 6020 car il commence par 0.
Merci d'avance pour votre aide. hugo.
# en awk:
Posté par totof2000 . Évalué à 2.
awk -F\~ ' /^ACT/ {
print $0
if (match($12,/^0/)) {
$12=$14
print $12 " " $14
}
print $0
}' toto
en supposant que ton fichier s'appelle toto.
[^] # Re: en awk:
Posté par totof2000 . Évalué à 2.
awk -F\~ ' /^ACT/ { # Recherche des lignes commencant par ACT
print $0 # Affiche la ligne avant transformation
if (match($12,/^0/)) { # si le 12e champ commence par 0
$12=$14 # remplacer le champ 12 par le champ 14
}
print $0 On affiche la ligne resultante. Attention j'ai omis un truc:si on veut conserver les ~ en separateur de champ il faut initialiser OFS a "~" ce qui se fait en insérant : OFS="~" avant le print $0
}' toto Fin du script Awk + nom dui fichier a traiter.
Suopprime le premier print $0 si tu ne veux pas tes lignes en 2 exemplaires.
Je laisse quelqu'un d'autre faire la meme chose en Perl.
[^] # Re: en awk:
Posté par hugo_migou . Évalué à 1.
awk 'BEGIN {FS="~";OFS="~"}
$12 > 999 {print $0}
$12 < 1000 {$12=$14;print $0}
END {}' test > test_res
Seul ic il me met des ~ a la fin de chaque ligne si elles n'ont pas 12 champs minimum. Comment peut on éviter ca?? je vais essayer ta solution aussi.
[^] # Re: en awk:
Posté par totof2000 . Évalué à 2.
Le nombre de champs est disponible via la variable NF. Je te laisse méditer dessus.
[^] # Re: en awk:
Posté par hugo_migou . Évalué à 1.
et ça marche trop bien trop vite... du coup plus de soucis... merci quand même, ca m'a éclairé.
# info sed
Posté par lcld . Évalué à 2.
Et pourtant, ici, une simple commande 's' suffit :
sed 's/^\(ACT\(~[^~]*\)\{10\}~\)0[^~]*\(~[^~]*~\)\([^~]*\)/\1\4\3\4/'
[^] # Re: info sed
Posté par totof2000 . Évalué à 5.
[^] # Re: info sed
Posté par hugo_migou . Évalué à 0.
[^] # Re: info sed
Posté par hugo_migou . Évalué à 1.
# "open + while + split + if + join + print + close" grace a RTFM
Posté par Mouns (site web personnel) . Évalué à 3.
voila ta réponse, je te demande au moins de faire un don au site linuxfr qui t'evite un zero a l'ecole ou d'etre lourdé de ton stage ( ce n'est pas compliqué d'ouvrir un livre ).
ce n'est qu'un gabarit, il manque plein de chose ... mais ca te sauvera la vie ( faut vraiment que cela soit crucial et urgent pour ne pas ouvrir un manuel et prendre le temps de le lire ).
open( IFILE, "<", "input.txt" );
open( OFILE, ">", "output.txt" );
while( <IFILE> ) {
chomp;
my @col = split( '~', $_ );
if ( ( $col[0] eq "ACT" ) && ( $col[12] =~ /^0/ ) ) {
$col[12] = $col[14];
}
print join( '~' , @col ), "\n";
}
close( IFILE );
close( OFILE );
[^] # Re: "open + while + split + if + join + print + close" grace a RTFM
Posté par hugo_migou . Évalué à -1.
[^] # Re: "open + while + split + if + join + print + close" grace a RTFM
Posté par Mouns (site web personnel) . Évalué à 4.
sinon, tu peux tenter une recursion mais cela reste encore une boucle implicite :
open( my $ifile, "<", "input.txt" );
open( OFILE, ">", "output.txt" );
sub recurs {
my $h = shift;
my $a = <$h>;
chomp;
my @col = split( '~', $_ );
if ( ( $col[0] eq "ACT" ) && ( $col[12] =~ /^0/ ) ) {
$col[12] = $col[14];
}
print OFILE join( '~' , @col ), "\n";
recurs( $h ) unless eof( $h );
}
recurs( $ifile );
close( $ifile );
close( OFILE );
Maintenant, explique moi comment traiter un fichier de N lignes sans faire une boucle ? Les instructions SIMD pour des traitements complexes gerant des acces disques n'existent pas encore il me semble mais je me trompe peut etre.
Penses tu serieusement que cat, grep, awk & co ne font pas de boucle quelque part ?
quel overhead représente un saut pour ton probleme si tu le resoud dans un langage interprété ? autant résoudre ton probleme en ASM, mais de toute facon je ne vois pas comment ne pas mettre de saut sans derouler.
cadeau : le source d'une version de cat pour OpenBSD http://mirror.sg.depaul.edu/pub/OpenBSD/src/bin/cat/cat.c
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.