Léa-Linux & amis :   LinuxFR   GCU-Squad   GNU
écriture script
Envoyé par: jet

Bonjour,
je suis nouveau sous Linux.
Je cherche à manipuler un fichier qui se présente sous la forme:

Titre1
Titre2
sous-titre1
soustitre2
données
.
.
.
end
données
.
.
.
end
end
sous-titre1
soustitre2
données
.
.
.
end
données
.
.
.
end
end
etc..

Mon but est d'extraire les lignes de données en fichiers séparés, en conservant les titres 1 et 2 puis les sous titres1 et 2, suivis des données avant "end". Il faudrait autant de fichiers que de paquets de données comprises entre soustitre et end ou end end.
Heu, qqun a compris, je m'y perd parfois, je fais des essais sous awk qui semble le plus approprié pour le moment.
Si qqun veut aider, j'apprécierai. Merci par avance.

Poste le Friday 6 May 2005 20:06:13
Répondre     Citer    
Re: écriture script
Envoyé par: Sve@r

Désolé, ton problème est insoluble. Il n'y a aucun moyen de distinguer le titre du sous-titre, ou le titre/sous-titre de la donnée...

Poste le Tuesday 10 May 2005 19:27:32
Répondre     Citer    
Re: écriture script
Envoyé par: jet

Hello,
je vais essayer d'être plus explicite, ce qui n'était pas le cas dans mon premier message. Mais pour répondre a Sve@r, je pense que c'est possible, et il me le confirmera après avoir vu la suite.
Voici donc un exemple de fichier que je veux transformer, qui contient des données sous une forme répétitive, je voudrais extraire les blocs de données (des coordonées) un par un, en les écrivant dans des fichiers qui sont incrémentés au fur et à mesure qu'ils sont lus.
Je souhaiterai que le titre général du fichier de départ soit repris en tête de chacun des fichiers (lignes 1 et 2), et que les sous-titres de section apparaissent également (lignes 3 et 4, puis après end\n end\n.
Voici un exemple:

!BIOSYM archive 3
PBC=OFF
input file for discover 435.6030
!DATE Thu Jan 13 11:46:39 2005
C01 -5.025863800 7.244002568 -2.013714777 MOL 1 cp C -0.100
C02 -5.621308166 8.441894104 -1.641637049 MOL 1 cp C -0.100
C03 -5.487535751 8.913697143 -0.340114590 MOL 1 cp C -0.100
C04 -4.760697134 8.183964782 0.613221110 MOL 1 cp C 0.179
C05 -4.141217551 6.973057864 0.227766329 MOL 1 cp C 0.179
C06 -4.285427926 6.516611169 -1.089195651 MOL 1 cp C -0.100
C07 -4.636362080 8.682850504 2.040567012 MOL 1 c' C 0.201
O072 -5.082137003 9.791345008 2.358442105 MOL 1 o' O -0.380
C08 -3.321835823 6.185377501 1.226036606 MOL 1 c' C 0.201
O081 -2.607491440 5.247603629 0.853231867 MOL 1 o' O -0.380
end
N -2.148307800 2.051270962 -20.085494995 LEUN D256 n4 N -0.500
CA -0.651043952 1.878017187 -20.083555222 LEUN D256 ca C 0.320
C -0.075287342 1.961853147 -18.664987564 LEUN D256 c' C 0.380
O -0.324314356 2.940160036 -17.949766159 LEUN D256 o' O -0.380
CB 0.025487572 2.959214211 -20.950561523 LEUN D256 c2 C -0.200
CG -0.277858555 3.069788218 -22.458589554 LEUN D256 c1 C -0.100
end
end
input file for discover 437.1630
!DATE Thu Jan 13 11:46:39 2005
C01 -4.351889556 7.079741676 -1.520970600 MOL 1 cp C -0.100
C02 -4.734089789 8.349428503 -1.110912678 MOL 1 cp C -0.100
C03 -4.514119725 8.754778304 0.200306444 MOL 1 cp C -0.100
C04 -3.916004573 7.886262812 1.125546338 MOL 1 cp C 0.179
C05 -3.518875921 6.595545174 0.703879342 MOL 1 cp C 0.179
C06 -3.738831683 6.210077354 -0.625717724 MOL 1 cp C -0.100
C07 -3.688085573 8.326146777 2.559519522 MOL 1 c' C 0.201
O072 -3.913608344 9.492763122 2.902060659 MOL 1 o' O -0.380
C08 -2.851271760 5.651878215 1.680951736 MOL 1 c' C 0.201

Explication: des blocs de coordonnées séparés par des doubles "end", avec deux sections dans chaque bloc séparées par un seul "end". Les doubles "end" sont suivis de deux lignes de titres pour le bloc. La longueur des sous sections permettrait sans doute de les différencier. Le nb de lignes de données dans l'exemple est très inférieur à la réalité...

VOici maintenant ce que j'ai écrit, très simple, pour extraire le premier bloc, et sur lequel je voudrais maintenant installer une boucle conditionnelle permettant de passer le "end" de sous-section, puis le double "end" de section...mais là j'ai échoué pour le moment.

BEGIN {
f=1
fichier="fichier"
fichier=fichier f
print "!BIOSYM archive 3" >fichier
print "PBC=OFF" >fichier
}
$1=="end" || $0=="" {exit}
NF>3 && NF<=9 {print $0 > fichier}
END {print "fini"}

f sera ma variable d'incrémentation pour les nom de fichiers successifs. Je m'appuie sur le nb de champs pour la lecture des lignes, la ligne vide signifiant la fin du fichier d'origine.
Actuellement un while à la suite de BEGIN ne me permet pas de faire tourner plus avant.
Si qqun peut aider, j'accueillerai toute suggestion (je débute), sinon je posterai les updates en fonction de ma progression.

Merci par avance.

Jet

Poste le Friday 13 May 2005 13:16:23
Répondre     Citer    
Re: écriture script
Envoyé par: marc ferraton

tu peux traiter des boucles si tu ouvre le fichir dans ton programme awk et de faire des getline,

mais tu peux aussi résoudre sur le stream normal en positionnant des variables de tag suivant tes lectures
ex:
BEGIN{
flag_debut=0
flag_titre_1=0
flag_stitre_1=0
flag_stitre_2=0
flag_bloc = 0
flag_données=0
} 
{
   if (flag_debut==0) 
   {
       if (flag_titre_1 == 0 )
       {
         titre_1 = $0
         flag_titre_1 = 1
       } 
       if (flag_titre_1 == 1 && flag_titre_2 == 0 )
       {
         titre_2 = $0
         flag_titre_2 = 1
         flag_debut=1
         flag_bloc = 1 
       }
   }
   if ( flag_bloc = 1 )
   {
      # ici lecture des sous titre
      # a ecrire smiling smiley
      # ensuite suivant si tu lis un end alors tu repositionne les flag pour traiter toin fichier
      if ( $0 == "end" && flag_données == 0 )
      {
          .....

par du principe que tu réexécutes ton programme à chaque nouvelle ligne du fichier, donc il te faut positionner des flag suivant la phase que tu as traitée, les lignes contenant les "end" te permette de repositionné le traitement à faire ( donc les flags..)

Poste le Friday 13 May 2005 23:21:40
Répondre     Citer    
Re: écriture script
Envoyé par: jet

Bonjour,
merci Marc, je vais tester, et je vous raconte...

A +

Poste le Saturday 14 May 2005 09:33:32
Répondre     Citer    
Re: écriture script
Envoyé par: lolo.doudou

hello,
on recupere systematiquement les 4 premieres lignes:
(titre + sous titre)

NR<5 { print }

on recupere egalement les 2 lignes qui suivent les "double end". pour cela on va utiliser un compteur

status>0 { status--; print }
/^end/ { compteur++ }
!/^end/ { compteur=0 }
compteur==2 { status=2 }

il faut initialiser la variable status à 0 pour eviter les ennuis
BEGIN { status=0 }



Il faut bien sur mettre tous ces elements dans l'ordre

awk '
BEGIN { status=0 }

NR<5 { print }

status>0 { status--; print }
/^end/ { compteur++ }
!/^end/ { compteur=0 }
compteur==2 { status=2 }
' nomfichier


Poste le Sunday 15 May 2005 08:30:12
Répondre     Citer    
Re: écriture script
Envoyé par: Eric92

En plus rustique, la cmmande csplit pourrait convenir,
exemple :
csplit -f prefixe nomfichier  /end/2 '{*}'

Poste le Monday 16 May 2005 03:27:48
Répondre     Citer    
Re: écriture script
Envoyé par: jet

Bonjour,
je voulais remercier ceux qui m'ont aidé, car le script fonctionne au poil après qqs ajustements.
Grand merci donc à Sve@r, Marc, Lolo et Eric pour leurs sugestions, Marc étant responsable de ce qui suit. Au cas où qqun serait intéressé, je me ferai une joie de communiquer.

VOici le résultat:

BEGIN {
flag_debut=0
flag_titre1=0
flag_titre2=0
flag_stitre1=0
flag_stitre2=0
flag_bloc=0
mol=1
flag_end=0
}
{
if (flag_debut==0) #lecture des titres 1 et 2
{if (flag_titre1==0)
{
titre_1=$0
flag_titre1=1
next
}
if (flag_titre1==1 && flag_titre2==0)
{
titre_2=$0
flag_titre2=1
flag_debut=1
next
}
}
if (flag_bloc==0) #lecture des sous-titres 1 et 2
{if ($1=="end") {next} #vérifie la presence du second end
if (flag_stitre1==0)
{
stitre_1=$0
flag_stitre1=1
next
}
if (flag_stitre1==1 && flag_stitre2==0)
{
stitre_2=$0
flag_stitre2=1
flag_bloc=1
print titre_1 > mol
print titre_2 > mol
print stitre_1 > mol
print stitre_2 > mol
next
}
}
if ($1=="end" && flag_end==0)
{
flag_end=1
print "end" > mol #écriture end en fin de coordonnées
mol=mol+1 #incrémentation du n°fichier
print titre_1 > mol #écrit titres et sous-titres en-tête du nouveau fichier
print titre_2 > mol #idem
print stitre_1 > mol #idem
print stitre_2 > mol #idem
next
}
if ($1=="end" && flag_end==1)
{
print "end" > mol
flag_bloc=0 #permet la lecture des nouveaux sous-titres
flag_stitre1=0 #idem
flag_stitre2=0 #idem
flag_end=0
mol=mol+1 #incrémentation du n°fichier
next
}
else print $0 > mol
}
END {print "fini"}


Poste le Monday 16 May 2005 16:34:18
Répondre     Citer    
Re: écriture script
Envoyé par: marc ferraton

voilà qui est bien,
tiens je viens de découvrir l'instruction next smiling smiley
d'habitude je m'*emm* avec les else, c'est nettement plus simple

mais ce sera pour la prochaine fois, je ne vais pas reprendre mes applis...




Poste le Monday 16 May 2005 23:37:31
Répondre     Citer    

Veuillez vous authentifier auparavant pour commenter.

 

Ce forum !
écriture script
Pour poser vos questions sur les scripts shell, le Perl, le C, etc... Attention : nous ne sommes pas des spécialistes du dev, ce forum est juste pour de petites aides ponctuelles concernant le développement et les outils de développement.

Sauf mention contraire, les documentations publiées sont sous licence Creative-Commons