#1 Le 12/11/2007, à 22:36
- graffity2199
[RESOLU] Extraire une chaine entre 2 délimiteurs dans un fichier
Bonjour à tous,
Je cherche depuis un bon moment comment extraire une ou des chaines de caractères d'un fichier séparé par des délimiteurs de mon choix (des chaines ou expressions régulières) pour la programmation d'un script bash. Je n'arrive pas à trouver des documentations suffisantes sur les commandes Unix, que ce soit dans les pages man (qui sont dépourvues d'exemples) ou dans notre wiki.
J'ai donc un fichier en entrée, et je souhaite par exemple récupérer toutes les chaines de caractères comprises entre begin et end.
Exemple de fichier d'entrée (programme pascal) :
program Hello(output);
procedure DireBonjour(nom: string);
begin writeln('salut ', nom, ' du monde de la programmation'); end;
var
a:string;
begin
write('veuillez saisir votre nom: ');
readln(a);
DireBonjour(a);
end.
J'aimerai donc retrouver dans un fichier de sorti les lignes suivantes :
writeln('salut ', nom, ' du monde de la programmation');
et
write('veuillez saisir votre nom: ');
readln(a);
DireBonjour(a);
Ceci est évidemment un exemple mais je ne voit pas quelle commande pourrait réaliser cela, j'ai essayé de me tourner vers cut et sed mais sans succès pour le moment. Avez vous des idées ?
Dernière modification par graffity2199 (Le 14/11/2007, à 22:14)
Hors ligne
#2 Le 12/11/2007, à 23:18
- ZondeR
Re : [RESOLU] Extraire une chaine entre 2 délimiteurs dans un fichier
Tiens, c'est marrant, je viens justement de passer une soirée à rechercher qqchose comme ça. Tu n'arriveras à rien avec cut à mon avis, avec sed, tu peux, mais qu'est-c que c'est imbuvable. Tu peux aussi t'en sortir avec awk, ils prétendent que c'est plus digeste que sed, j'en suis pas convaincu, mais je me dis que ça peut pas être pire.
Donc, je te dis ou j'en suis, la meilleure page que j'ai trouvée sur sed, c'est celle-ci:
http://www.grymoire.com/Unix/Sed.html
sinon, piqué sur cette page http://www.pixelbeat.org/cmdline.html, une formule sed qui marche à moitié:
sed -n 's/.*begin\ \(.*\)end.*/\1/ip' ton_fichier
avec ça, tu récupères writeln('salut ', nom, ' du monde de la programmation');, mais pas l'autre...
C'est à mon avis parce que sed fait les choses ligne par ligne, donc, il vaudrait mieux utiliser autre chose aussi.
Avec un grep, tu pourrais peut-être faire qqchose comme
grep -A10 begin ton_fichier|grep -B10 end
Enfin, faut combiner quoi ou faut tomber sur qqun de meilleur que moi .
Peut-être devrais-tu aller sur un forum dédier à ce genre de saloperie comme:
http://www.unix.com/shell-programming-scripting/
Dernière modification par ZondeR (Le 12/11/2007, à 23:29)
Hors ligne
#3 Le 13/11/2007, à 00:01
- abetsic
Re : [RESOLU] Extraire une chaine entre 2 délimiteurs dans un fichier
Bonsoir,
ce problème m'a perturbé il y a un moment, j'avais trouvé un gros hack dégueulasse qui m'avait permis de faire ce que je voulais mais c'était vraiment crade... Par contre j'avais essayé avec vim et là j'avais réussi beaucoup plus facilement à insérer un nombre inconnu de retours à la ligne dans l'expression régulière...
J'avais vaguement regardé du coté du scripting de vim, et je crois que c'était possible de faire quelque chose mais bon c'était un peu sortir le bazooka pour tuer une mouche et je me suis contenté du truc dégueu que j'avais... Je vais essayer d'aller le retrouver mais je ne te promets rien.
edit : ouais finalement j'avais réussi à trouver l'expression régulière qui matchait une seule ligne là o๠je voulais faire mon changement... Mais avec sed traiter plusieurs lignes c'est une vrai plaie ! Si tu trouves une solution je serai content de la voir.
Bonne chance
Dernière modification par abetsic (Le 13/11/2007, à 00:08)
Hors ligne
#4 Le 13/11/2007, à 11:10
- Laurent Marzullo
Re : [RESOLU] Extraire une chaine entre 2 délimiteurs dans un fichier
tu peux essayer ca:
cat toto.pl | awk '/begin/ { mustprint=1; if ( match($0,"begin.+end") ) { str=$0; printf "%s\n", gensub("begin[[:space:]]*(.*)[[:space:]]*end[.;]","\\1","g",str); mustprint=0}; next; } /end/ { mustprint=0;next } { if ( mustprint == 1 ) printf("str = %s\n",$0) }'
#5 Le 13/11/2007, à 13:45
- philippe_g
Re : [RESOLU] Extraire une chaine entre 2 délimiteurs dans un fichier
Bonjour,
Pour ce genre de travail, PERL est ton ami:
Hors ligne
#6 Le 13/11/2007, à 22:19
- graffity2199
Re : [RESOLU] Extraire une chaine entre 2 délimiteurs dans un fichier
Merci pour vos réponses, voici l'état d'avancement de mes recherches.
Comme la supposé ZondeR, j'ai essayé quelquechose avec
sed -n 's/.*begin\ \(.*\)end.*/\1/ip' fichier
mais même en concaténant le fichier sur une seule ligne et en ajoutant un g, on obtient seulement l'une des deux occurences.
Quand au script awk de laurent, il me fait une erreur avec la fonction gensub :
awk: line 2: function gensub never defined
.
mais je ne connait que très peu awk, j'ai essayé de remplacer la fonction par gsub mais une erreur est toujours persistante.
Du coté de perl, comme l'a suggéré laurent, j'ai essayé la commande
perl -ne 'print if /begin/ .. /end/' fichier
qui affiche :
begin writeln('salut ', nom, ' du monde de la programmation'); end;
begin
write('veuillez saisir votre nom: ');
readln(a);
DireBonjour(a);
end.
Ce qui semble presque bon, mais elle renvoi également des instructions qui pourraient être présentes sur la ligne (par exemple si on rajoute le var sur la première ligne après le end, il sera lui aussi retourné. De plus, elle renvoi également les chaines begin et end.
On y est presque, mais pas tout à fait, il faut que je persévère. Je tiens à préciser que je n'ai pas de motif imbriqués comme
begin var a:string; begin var b:string; end; var c:string; end;
En tout cas merci pour vos réponses.
Dernière modification par graffity2199 (Le 13/11/2007, à 22:25)
Hors ligne
#7 Le 13/11/2007, à 22:39
- Gojita
Re : [RESOLU] Extraire une chaine entre 2 délimiteurs dans un fichier
c'est normal que gsub ne fonctionna pas. Elle renvoie l'index ou se trouve la chaine.
Alors que gensub devrait renvoyer la chaine elle-même.
Essai d'installer 'gawk' au lieu de mawk.
Il y a 10 sortes de personnes
Celles qui savent compter en binaires et les autres.
Hors ligne
#8 Le 13/11/2007, à 23:24
- Alain.g
Re : [RESOLU] Extraire une chaine entre 2 délimiteurs dans un fichier
Ce qui semble presque bon, mais elle renvoi également des instructions qui pourraient être présentes sur la ligne (par exemple si on rajoute le var sur la première ligne après le end, il sera lui aussi retourné. De plus, elle renvoi également les chaines begin et end.
Salut
Je pense qu'il fallait plutà´t regarder le second exemple du lien donné par philippe_g. Par contre dans l'exemple on utilise -pe, alors que ça doit être -ne :
perl -0777 -ne 'print "$1\n" while /begin(.*?)end/gs' fichier
ou bien en testant qu'il y a bien un ";" ou "\n" avant le end:
perl -0777ne 'print "$1\n" while /begin(.*?)[;\r\n]+\s*end/gs' fichier
Il faudrait quand même développer pour que ça soit vraiment utilisable
Dernière modification par Alain.g (Le 13/11/2007, à 23:33)
Xubuntu Karmic !
Hors ligne
#9 Le 14/11/2007, à 21:40
- graffity2199
Re : [RESOLU] Extraire une chaine entre 2 délimiteurs dans un fichier
Merci ! ca marche sans aucun problème, j'utilise donc la première version.
Hors ligne