Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#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 big_smile.

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 smile

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:

http://www.linux-kheops.com/doc/perl/fa … ignes_entr

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

graffity2199 a écrit :

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