[Awk] Pb de substitution dans un fichier
Résolu/Fermé
benjyd
Messages postés
11
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
10 janvier 2009
-
8 mars 2006 à 11:57
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 - 10 mars 2006 à 10:52
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 - 10 mars 2006 à 10:52
A voir également:
- [Awk] Pb de substitution dans un fichier
- Fichier rar - Guide
- Fichier host - Guide
- Fichier iso - Guide
- Comment réduire la taille d'un fichier - Guide
- Comment ouvrir un fichier epub ? - Guide
18 réponses
renisaac
Messages postés
2043
Date d'inscription
dimanche 22 août 2004
Statut
Contributeur
Dernière intervention
15 mai 2021
138
8 mars 2006 à 12:10
8 mars 2006 à 12:10
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
benjyd
Messages postés
11
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
10 janvier 2009
8 mars 2006 à 14:08
8 mars 2006 à 14:08
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
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 894
9 mars 2006 à 12:19
9 mars 2006 à 12:19
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".
benjyd
Messages postés
11
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
10 janvier 2009
9 mars 2006 à 13:59
9 mars 2006 à 13:59
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
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
9 mars 2006 à 14:38
9 mars 2006 à 14:38
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
benjyd
Messages postés
11
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
10 janvier 2009
9 mars 2006 à 14:44
9 mars 2006 à 14:44
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...
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
9 mars 2006 à 14:47
9 mars 2006 à 14:47
J'ai édité mon post ci-dessus pour faire les tests en une ligne, avec un seul if. Celà rend le code plus compact sans trop nuire à la lisibilité.
Dal
Dal
benjyd
Messages postés
11
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
10 janvier 2009
9 mars 2006 à 14:54
9 mars 2006 à 14:54
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
benjyd
Messages postés
11
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
10 janvier 2009
9 mars 2006 à 14:56
9 mars 2006 à 14:56
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...
benjyd
Messages postés
11
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
10 janvier 2009
9 mars 2006 à 15:13
9 mars 2006 à 15:13
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 )?
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
9 mars 2006 à 18:18
9 mars 2006 à 18:18
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
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
9 mars 2006 à 18:37
9 mars 2006 à 18:37
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
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 567
9 mars 2006 à 19:08
9 mars 2006 à 19:08
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]$
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 567
9 mars 2006 à 19:35
9 mars 2006 à 19:35
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]$
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
9 mars 2006 à 19:57
9 mars 2006 à 19:57
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
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 567
9 mars 2006 à 20:32
9 mars 2006 à 20:32
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; }
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 567
9 mars 2006 à 20:55
9 mars 2006 à 20:55
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
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 894
9 mars 2006 à 23:02
9 mars 2006 à 23:02
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 ;-))
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 567
9 mars 2006 à 22:34
9 mars 2006 à 22:34
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.
benjyd
Messages postés
11
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
10 janvier 2009
10 mars 2006 à 10:12
10 mars 2006 à 10:12
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!
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
10 mars 2006 à 10:52
10 mars 2006 à 10:52
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