[Awk] Pb de substitution dans un fichier
Résolu
benjyd
Messages postés
11
Statut
Membre
-
[Dal] Messages postés 6373 Statut Contributeur -
[Dal] Messages postés 6373 Statut Contributeur -
Bonjour,
Voici mon soucis :
J'ai un fichier en entrée avec en tête de ligne 05 et en 31/32ème position 01.
Mon problème est de remplacer ce 05 pas 06
Par exemple :
05 1496321684067 1478963 478901
par 06 1496321684067 1478963 478901
Il me semble que c'est réalisable mais je ne sais plus si je peux utiliser awk seul ou si je dois le | avec un seb.
Merci d'avance pour vos réponses
Benjyd
Voici mon soucis :
J'ai un fichier en entrée avec en tête de ligne 05 et en 31/32ème position 01.
Mon problème est de remplacer ce 05 pas 06
Par exemple :
05 1496321684067 1478963 478901
par 06 1496321684067 1478963 478901
Il me semble que c'est réalisable mais je ne sais plus si je peux utiliser awk seul ou si je dois le | avec un seb.
Merci d'avance pour vos réponses
Benjyd
A voir également:
- [Awk] Pb de substitution dans un fichier
- Fichier bin - Guide
- Comment réduire la taille d'un fichier - Guide
- Comment ouvrir un fichier epub ? - Guide
- Fichier rar - Guide
- Fichier .dat - Guide
18 réponses
Salut Benjyd,
je pense que
Renisaac
je pense que
sed -s /05/06/ fichier_entrée > fichier_sortiedevrais faire l'affaire. Il te remplace a chaque ligne la première occurence de 05 par 06.
Renisaac
J'avais essyé en l'ouvrant avec vi un
:%s/^05/06/g mais le pb c'est que j'ai environ une ligne sur 2 qui est censée être affectée alors que là c'est toutes les lignes qui sont modifiées
:%s/^05/06/g mais le pb c'est que j'ai environ une ligne sur 2 qui est censée être affectée alors que là c'est toutes les lignes qui sont modifiées
Salut,
Il faudrait que tu précises si tu veux remplacer toutes les occurences commençant par "05" ou seulement celles commençant par "05" et se terminant par "01".
Il faudrait que tu précises si tu veux remplacer toutes les occurences commençant par "05" ou seulement celles commençant par "05" et se terminant par "01".
Oui en effet je me suis peut-être mal exprimé
j'ai en effet la plupart de mes lignes qui commencent par 05 et je ne souhaite changer que celles qui commencent par 05 et qui on en 31 et 32 ème caractères 0 et 1 tout en sachant qu'entre le 05 et le 01 j'ai divers caractères mais que la position de 0/1 est toujours en 31 et 32 et que 01 ne se situe pas en fin de ligne mais en plein milieu!
Encore désolé pour cet oubli et merci pour vos futures réponses.
Cdlmt
B1j
j'ai en effet la plupart de mes lignes qui commencent par 05 et je ne souhaite changer que celles qui commencent par 05 et qui on en 31 et 32 ème caractères 0 et 1 tout en sachant qu'entre le 05 et le 01 j'ai divers caractères mais que la position de 0/1 est toujours en 31 et 32 et que 01 ne se situe pas en fin de ligne mais en plein milieu!
Encore désolé pour cet oubli et merci pour vos futures réponses.
Cdlmt
B1j
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Salut benjyd,
Pour çà, j'utiliserai Perl.
Dans cet exemple, seule la 4ème ligne rempli les conditions. Le code de testpl.pl :
Dal
Pour çà, j'utiliserai Perl.
$ cat data.txt 03 1496321684067 1478963 478903 098678 04 1496321684067 1478963 478901 098678 05 1496321684067 1478963 478903 098678 05 1496321684067 1478963 478901 098678 05 1496321684067 1478963 478903 098678 $ ./testpl.pl 03 1496321684067 1478963 478903 098678 04 1496321684067 1478963 478901 098678 05 1496321684067 1478963 478903 098678 06 1496321684067 1478963 478901 098678 05 1496321684067 1478963 478903 098678
Dans cet exemple, seule la 4ème ligne rempli les conditions. Le code de testpl.pl :
#!/usr/bin/perl
open(FICH, "data.txt");
while (<FICH>) {
if ( (/^05/) && (index($_,"01",29) eq "29") ) {
$_ =~ s/^05/06/;
}
print "$_";
}
close(FICH);
Dal
C'est bien ce que je pensais mais ne m'y connaissant pas en Perl je redoutais un peu d'en arriver là, je te remercie je teste de suite...
C'est nickel merci beaucoup, je pense que je vais me mettre un peu à Perl si vous avez du "Perl pour les nuls" ça peut m'intéresser!
En tout cas merci et j'espère pouvoir un jour rendre la pareille
B1j
En tout cas merci et j'espère pouvoir un jour rendre la pareille
B1j
Pour info, voici le code que j'ai utilisé :
#!/usr/bin/perl
open(FICH, "essai.txt");
while (<FICH>) {
if ( (/^05/) && (index($_,"01",32) eq "32") ) {
$_ =~ s/^05/06/;
}
print "$_";
}
close(FICH);
car en fait le 01 se trouvait en 33 et 34!!
Encore merci...
#!/usr/bin/perl
open(FICH, "essai.txt");
while (<FICH>) {
if ( (/^05/) && (index($_,"01",32) eq "32") ) {
$_ =~ s/^05/06/;
}
print "$_";
}
close(FICH);
car en fait le 01 se trouvait en 33 et 34!!
Encore merci...
par contre, est-ce normal que mes fichiers (avant et après) aient une taille différent (dans le script j'ai remplacé essai par avant et je lance conv.pl >apres.txt )?
Pour débuter avec Perl, ce lien est pas mal (en anglais) :
http://www.troubleshooters.com/codecorn/littperl/
Pour la différence de taille, je ne crois pas que ce soit normal... ton fichier avant.txt est bien un fichier ASCII Unix ? Lequel est plus petit ? La différence est de quel ordre ? Peux-tu les identifier avec un diff avant.txt apres.txt ?
Dal
http://www.troubleshooters.com/codecorn/littperl/
Pour la différence de taille, je ne crois pas que ce soit normal... ton fichier avant.txt est bien un fichier ASCII Unix ? Lequel est plus petit ? La différence est de quel ordre ? Peux-tu les identifier avec un diff avant.txt apres.txt ?
Dal
A la ligne de commande, il y a aussi "perldoc".
tape :
perldoc perldoc
perldoc perl
pour apprendre à t'en servir.
La base de données CPAN
http://www.cpan.org/
http://search.cpan.org/
contient une ressource inépuisable de modules qui t'évitent d'avoir à réinventer la roue, pour faire tout un tas de choses. Tu les télécharges ou tu les installes directement à la ligne de commande, en mode intéractif avec :
perl -MCPAN -e 'shell'
install lemodulerecherché
Celà télécharge le module et ses éventuelles dépendances, le teste et l'installe.
Dal
tape :
perldoc perldoc
perldoc perl
pour apprendre à t'en servir.
La base de données CPAN
http://www.cpan.org/
http://search.cpan.org/
contient une ressource inépuisable de modules qui t'évitent d'avoir à réinventer la roue, pour faire tout un tas de choses. Tu les télécharges ou tu les installes directement à la ligne de commande, en mode intéractif avec :
perl -MCPAN -e 'shell'
install lemodulerecherché
Celà télécharge le module et ses éventuelles dépendances, le teste et l'installe.
Dal
Salut,
je propose une autre solution( j'ai pris le cas de Dal)
Tu peut aussi utiliser la ligne de commande, pas besoin de script
je propose une autre solution( j'ai pris le cas de Dal)
#! /usr/bin/perl
use warnings;
while (<DATA>) {
s/^05((?:.){28}01.+)/06$1/;
print;
}
# j'utilse le handle DATA et je lit à partire de END
# donc remplace DATA avec le handle de ton fichier
# open(FICH, "data.txt") or die "Impossible ovrir fichir : $!\n";
# et tu utilise while (<FICH>)
__END__
03 1496321684067 144478963 478903 098678
04 1496321684067 147844963 478901 098678
05 1496321684067 147896443 478903 098678
05 1496321684067 147894463 478901 098678
05 1496321684067 147896443 478903 098678
Tu peut aussi utiliser la ligne de commande, pas besoin de script
[lamitest@localhost corbeille]$ cat vider
03 1496321684067 14478963 478903 098678
04 1496321684067 14744963 478901 098678
05 1496321684067 14789643 478903 018678
05 1496321684067 14789463 478901 098678
05 1496321684067 14789443 478903 098678
[lamitest@localhost corbeille]$ perl -pi.orig -e 's/^05((?:.){28}01.+)/06$1/' vider
[lamitest@localhost corbeille]$ cat vider
03 1496321684067 14447963 478903 098678
04 1496321684067 14744963 478901 098678
05 1496321684067 14789443 478903 018678
06 1496321684067 14784463 478901 098678
05 1496321684067 14786443 478903 098678
[lamitest@localhost corbeille]$ cat vider.orig
03 1496321684067 14447863 478903 098678
04 1496321684067 14784963 478901 098678
05 1496321684067 14786443 478903 018678
05 1496321684067 14789463 478901 098678
05 1496321684067 14786443 478903 098678
[lamitest@localhost corbeille]$
Traduction de la documentation Perl http://perl.enstimac.fr/
J'ai la même taille.
J'ai la même taille.
[lamitest@localhost corbeille]$ diff -c vider vider.orig *** vider 2006-03-09 19:17:11.000000000 +0100 --- vider.orig 2006-03-09 19:16:25.000000000 +0100 *************** *** 1,5 **** 03 1496321684067 144478963 478903 098678 04 1496321684067 147844963 478901 098678 05 1496321684067 147896443 478903 018678 ! 06 1496321684067 147894463 478901 098678 05 1496321684067 147896443 478903 098678 --- 1,5 ---- 03 1496321684067 144478963 478903 098678 04 1496321684067 147844963 478901 098678 05 1496321684067 147896443 478903 018678 ! 05 1496321684067 147894463 478901 098678 05 1496321684067 147896443 478903 098678 [lamitest@localhost corbeille]$ du -h vide* 4,0K vider 4,0K vider.orig [lamitest@localhost corbeille]$
Salut lami20j,
elle est très cool ta regex 's/^05((?:.){28}01.+)/06$1/' ...
Sur mes données elle marche avec 27 à la place de 28. Sinon, peux-tu l'expliquer (surtout la partie entre parenthèses) ?
Est-elle compatible avec sed ?
(auquel cas un sed -i ferait aussi l'affaire)
Dal
elle est très cool ta regex 's/^05((?:.){28}01.+)/06$1/' ...
Sur mes données elle marche avec 27 à la place de 28. Sinon, peux-tu l'expliquer (surtout la partie entre parenthèses) ?
Est-elle compatible avec sed ?
(auquel cas un sed -i ferait aussi l'affaire)
Dal
Et à la fin encore 2 version qui devront être plus rapides
Chez toi c'est 27 puisque tu cherches les postions 30 et 31 pas 31 et 32
=============================================
Chez toi c'est 27 puisque tu cherches les postions 30 et 31 pas 31 et 32
while (<DATA>) {
s/^05 # debut ligne 05
( # je capture le rest dans $1
(?: # paranthèse non capturante
. # n'importe quel caractère
) # donc je ne capture pas le resultat
# donc pas de consomation de texte
{27} # exact 27 fois : 05 + 27 =29
# donc après la pos 30 pour 0
# et 31 pour 1
# chez toi ça marche avec 27 puisque
# 0 est dans la postion 30 (pas 31)
01 # 01 après 27+2 donc postiton 30 et 31
.+ # au moins un caractère (donc 01 pas en fin de ligne)
) # fin de la capture $1
/06$1/x; # 06 concatené avec $1
# modificateur x pour commentaires dans regex
print;
}
=============================================
#! /usr/bin/perl
use warnings;
while (<DATA>) {
s/^05 # debut ligne 05
( # je capture le rest dans $1
(?: # paranthèse non capturante
. # n'importe quel caractère
) # donc je ne capture pas le resultat
# donc pas de consomation de texte
{27} # exact 27 fois : 05 + 27 =29
# donc après la pos 30 pour 0
# et 31 pour 1
# j'ai toi ça marche avec 27 puisque
# 0 est dans la postion 30 (pas 31)
(?=01) # 01 après 27+2 donc postiton 30 et 31
# cette fois je fait un test avant
# qui veut dire que je regarde si après
# la positon 29 (ton cas) j'ai 0 suit de 1
# qui ne consomme pas de texte (plus rapide)
.+ # au moins un caractère (donc 01 pas en fin de ligne)
) # fin de la capture $1
/06$1/x; # 06 concatené avec $1
# modificateur x pour commentaires dans regex
# la regex : s/^05((?:.){27}(?=01).+)/06$1/
print;
}===========================================
#! /usr/bin/perl
use warnings;
while (<DATA>) {
# j'utilise seulement un test avant donc pas de capture en $1
# et je remplace que 05
# tout chaine qui commance avec 05
# et après contient un chaine qui a dans les postions
# 30 et 31, 0 suit de 1
# pas en fin de ligne
# je remplace 05 avec 06
s/^05(?=(?:.){27}01.+)/06/;
print;
}
Re,
Pour sed je ne crois pas. Je ne sais pas si le regex de sed utilise les test avant (?=...) ou les paranthèses non-capturante (?:...)
Il faut demander jipicy, c'est lui mon préféré pour sed
Pour sed je ne crois pas. Je ne sais pas si le regex de sed utilise les test avant (?=...) ou les paranthèses non-capturante (?:...)
Il faut demander jipicy, c'est lui mon préféré pour sed
Salut vous tous,
Ben honnêtemment pour "sed" je sais pas et je crois pas que l'on puisse faire la même chose qu'en "perl", du moins avec "sed" tout seul (peut être que combiné avec "grep" et/ou "awk"...).
En tout cas chapeau bas "lami20j" pour le script et les explications.
J'ai encore jamais touché à "perl", mais je crois que je vais m'y mettre sérieusement ;-))
PS. [Dal] => Ton tien était bien aussi ;-))
Ben honnêtemment pour "sed" je sais pas et je crois pas que l'on puisse faire la même chose qu'en "perl", du moins avec "sed" tout seul (peut être que combiné avec "grep" et/ou "awk"...).
En tout cas chapeau bas "lami20j" pour le script et les explications.
J'ai encore jamais touché à "perl", mais je crois que je vais m'y mettre sérieusement ;-))
PS. [Dal] => Ton tien était bien aussi ;-))
Re Dal,
et pour pousser encore
ensuite 5
et le test avant expliqué dans le message précedent
En ce cas tout reviens à remplace 5 avec 6
Tant que la regex ne consomme pas de texte elle est rapide.
et pour pousser encore
s/(?<=^0)5(?=(?:.){27}01.+)/6/;donc je fait un test arrière pour voir si j'ai 0 en début de ligne
ensuite 5
et le test avant expliqué dans le message précedent
En ce cas tout reviens à remplace 5 avec 6
Tant que la regex ne consomme pas de texte elle est rapide.
Merci pour votre aide...
à la prochaine
ps, j'aimerai avoir un avis sur mon forum si ça vous dérange pas :
http://pasdepanique.misterforum.com
il est tout récent donc personne dessus!
à la prochaine
ps, j'aimerai avoir un avis sur mon forum si ça vous dérange pas :
http://pasdepanique.misterforum.com
il est tout récent donc personne dessus!
Salut lami20j,
Merci pour tes explications qui sont très claires. C'est impressionnant :)
perldoc perlre
semble confirmer que les expressions ayant une syntaxe d'une paire de parenthèses avec un point d'interrogation comme premier caractère entre les parenthèses correspondent à des fonctionnalités inexistantes dans les outils standard tels que awk (ou sed je présume). Il semblerait donc qu'on ne dispose pas de la même faculté de se promener dans la ligne en avant et en arrière pour y faire des tests sans capturer du texte sous sed, awk,...
Dans le lien que tu as fourni, j'ai trouvé le PerlReTut, qui m'a l'air plus abordable que la page de manuel perlre :
http://perl.enstimac.fr/DocFr/perlretut.html
Dal
Merci pour tes explications qui sont très claires. C'est impressionnant :)
perldoc perlre
semble confirmer que les expressions ayant une syntaxe d'une paire de parenthèses avec un point d'interrogation comme premier caractère entre les parenthèses correspondent à des fonctionnalités inexistantes dans les outils standard tels que awk (ou sed je présume). Il semblerait donc qu'on ne dispose pas de la même faculté de se promener dans la ligne en avant et en arrière pour y faire des tests sans capturer du texte sous sed, awk,...
Dans le lien que tu as fourni, j'ai trouvé le PerlReTut, qui m'a l'air plus abordable que la page de manuel perlre :
http://perl.enstimac.fr/DocFr/perlretut.html
Dal