|
|
|
|
Salut,
Je ne vois pas très bien où tu places tes "paragraphes" 1, 2 et 3 dans ton exemple ci-dessus. Si ce que tu veux afficher ce sont des lignes (c'est à dire une suite de caractères avec CR au bout), tu peux utiliser grep, et l'option -v ou --invert-match pour les lignes ne contenant pas l'objet de la recherche (du moins dans le GNU grep). Dal
|
Salut,
en fait on n'a même pas besoin d'avoir des paragrphes tant qu'on est sur de ça commence par DDD et finissent par FFF. #! /usr/bin/perl
use warnings;use strict;
undef $/;
my $fic = <>;
pos($fic)=0;
while ( $fic =~ /DDD/g ){
if ($fic =~ /\G(.*XXX.*FFF)/){
print $1;
}
}Je ne l'ai pas testé mais l'algo est suivant :
- je récupère le contenu de fichier dans une variable scalaire (mode slurp) - je fais une recherche progressive de DDD et j'affiche le contenu de la chaine jusqu'à FFF uniquement si quelque part j'ai XXX entre DDD et FFF) pour ça j'utilise le modificateur g et l'assertion \G Si je me rappelle bien Dal a des bonnes connaissances en Perl donc il peut corriger mon script. Je suis sous Win maintenant et je ne peux pas tester. Pour execution perl /rep/scripts/extrat.pl nom_fichier lami20j
|
Encore une chose si jamais tu essaies le script.
Il faut inverser le sens puisque tu as besoin de Comment extraire les paragraphes ne contenant pas Donc au lieu de $fic =~ /\G(.*XXX.*FFF)/ écrit $fic !~ /\G(.*XXX.*FFF)/ lami20j |
Argh stop pitié pas de PERL
Vos solution sont surement bonne mais hélas ne me servent pas.
|
Re,
C'est dommage de ne pas utiliser Perl, car c'est un outil très puissant pour la manipulation de texte. Je comprend mieux ton concept de "paragraphe". Je ne connais pas bien awk, mais s'agissant de sed, à ma connaissance celui-ci travaille sur des lignes. Là tes "paragraphes" sont composés d'un nombre indéterminé de lignes avec des délimiteurs situés sur des lignes différentes. Tu peux cependant faire un script shell qui met dans une variable les "paragraphes" en question en fonction des délimiteurs et qui contrôle pour chaque ligne faisant partie du paragraphe si ton marqueur "XXX" y figure. Tu fais une boucle (par exemple en bash ou sh) : while read ligne do (...) done <les_datas.txt et dedans tu mets tes tests sed sur chaque $ligne, la variable de stockage des paragraphes (initialisée si c'est un marqueur de début, mise à jour sinon), un drapeau si le marqueur "XXX" est présent, un test d'affichage du contenu de la variable de stockage du paragraphe courant en fonction du drapeau (si le marqueur de fin de paragraphe est atteint), etc. Je n'ai pas le temps de te faire le script tout cuit, mais c'est comme çà que je ferai. Dal |
N'ayant pas le choix, j'ai deja commencé un truc dans ce genre.
Dommage de ne pas avoir la commande toute simple qui tue, car les fichiers à traiter sont énormes. Merci tout de même.. En esperant qu'un petit genie... |
|
Bonsoir,
Une astuce pour ne pas trop te pourrir la vie :) Avec sed seulement, on oublie (travail ligne/ligne, donc pas top) Avec awk seulement, ça doit être fesable, mais imbittable Avec les deux ensemble par contre :) awk travaillant sur des enregistrements et non sur des lignes ( le separateur d'enregistrement est \n par defaut) ça doit être réalisable.... Voyons un peu... La premiere chose a faire est d'avoir un separateur de champ... sed -e 's/\(^DDD.*\)/RECORD_SEP\1/' -e 's/\(^FFF.*\)/\1RECORD_SEP/' fichierLà on ajoute RECORD_SEP avant les lignes commencant par DDD et aprés les lignes commencant par FFF. On obtient quelque chose du genre: RECORD_SEPDDDblablabla blablablalll blablablammmmmmmm FFF blablablassRECORD_SEP RECORD_SEPDDD blablabla blablablaoo lsdqkgsqdXXX blablabla FFF blablabladdRECORD_SEP RECORD_SEPDDD blablablaqq blablablasd FFF blablabla RECORD_SEPSoit 6 enregistrements (C'est la faiblesse), en affinant, on doit pouvoir recuperer 3 enregistrements IE: DDDblablabla blablablalll blablablammmmmmmm FFF blablablass RECORD_SEPDDD blablabla blablablaoo lsdqkgsqdXXX blablabla FFF blablabladd RECORD_SEPDDD blablablaqq blablablasd FFF blablablaMais c'est pas grave :) Maintenant, qu'on a ces champ, il suffit de passer ça a awk, en lui demendant d'afficher les enregistrement qui nous sont utiles... Quelques infos: Pour ecraser le separateur de champ par defaut, il faut renseigner la variable RS dans un bloque BEGIN tant qu'a faire pour ne le faire qu'une fois au début du traitement BEGIN{ RS="RECORD_SEP" }la syntaxe pour afficher un enregistrement s'il correspond a une reg_exp est:/reg_exp/{ print $0} ($0 représente l'enregistrement courant)L'inverse:!/reg_exp/{ print $0}Ce qui nous donne:awk 'BEGIN{ RS="RECORD_SEP" } /DDD.*XXX.*FFF.*/ { print $0 }' pour matcher un paragraphe avec XXX etawk 'BEGIN{ RS="RECORD_SEP" } !/DDD.*XXX.*FFF.*/ && /DDD.*FFF.*/ { print $0 }' pour matcher un paragraphe sans XXX
Pour info: L'expression !/DDD.*XXX.*FFF.*/ ne suffit pas, elle retourne aussi les enregistrement vide (dus aux RECORD_SEP RECORD_SEP généré par sed plus haut) Donc: $ sed -e's/\(^DDD.*\)/RECORD_SEP\1/' -e 's/\(^FFF.*\)/\1RECORD_SEP/' test |awk 'BEGIN{ RS="RECORD_SEP" } /DDD.*XXX.*FFF.*/ { print $0 }'
DDD blablabla
blablablaoo
lsdqkgsqdXXX blablabla
FFF blablabladd
$ sed -e's/\(^DDD.*\)/RECORD_SEP\1/' -e 's/\(^FFF.*\)/\1RECORD_SEP/' test |awk 'BEGIN{ RS="RECORD_SEP" } !/DDD.*XXX.*FFF.*/ && /DDD.*FFF.*/ { print $0 }'
DDDblablabla
blablablalll
blablablammmmmmmm
FFF blablablass
DDD blablablaqq
blablablasd
FFF blablablaCa doit repondre à ton attente :)
(PS: je sais, c'est optimisable) Une belette, un lapin !? C'est pas normal!
|
Salut Adrien,
Chapeau bas Mister Severe ;-)) Effectivement comme l'a dit lami20j, tu m'ôtes des maux de la boîte cranienne ;-)) Bon en attendant en essayant d'optimiser (un tant soit peu) je suis arrivé à ça : sed 's/\(DDD\)/==\1/' fich.txt | awk 'BEGIN { RS="==" } !/XXX/ { print $0 }'
DDDblablabla
blablablalll
blablablammmmmmmm
FFF blablablass
DDD blablablaqq
blablablasd
FFF blablabla
$ sed 's/\(DDD\)/==\1/' fich.txt | awk 'BEGIN { RS="==" } /XXX/ { print $0 }'
DDD blablabla
blablablaoo
lsdqkgsqdXXX blablabla
FFF blablabladdMerci Adrien.
Z'@+...che.JP : Zen, my Nuggets ! ;-) Le savoir n'est bon que s'il est partagé. |
Bravo !
Content de te revoir sur le forum :) En fait, on peut même se passer de sed, puisque "DDD" est déjà un délimiteur :) .. on pourrai simplement le remettre dans l'instruction print. $ awk 'BEGIN { RS="DDD" } /XXX/ { print "DDD"$0 }' < fich.txt
DDD blablabla
blablablaoo
lsdqkgsqdXXX blablabla
FFF blablabladd
$ awk 'BEGIN { RS="DDD" } \!/XXX/ && /.*FFF.*/ { print "DDD"$0 }' < testsed.txt
DDDblablabla
blablablalll
blablablammmmmmmm
FFF blablablass
DDD blablablaqq
blablablasd
FFF blablabla
Enfin, pour que celà marche (cette syntaxe, comme celle de jipicy), il faut que les délimiteurs DDD et FFF ne risquent pas de se retrouver ailleurs dans le corps du paragraphe et que l'on n'ait donc pas à vérifier qu'ils soient en début de ligne. Dal
|
Résultats pour (sed) extraction d'une partie d'un fichier if
Résultats pour (sed) extraction d'une partie d'un fichier if
Résultats pour (sed) extraction d'une partie d'un fichier if
Résultats pour (sed) extraction d'une partie d'un fichier if