Moulinette awk (ajout de champs) pour un newb

Résolu
matthieu -  
 matthieu -
Bonjour,
je ne suis pas du tout informaticien, ce qui explique que je bute deja sur ce probleme simplissime:
J'ai un fichier de taille variable, que je veux reecrire en rajoutant des lignes.
Ex:
j'ai le fichier ;

********
toto1
titi
********
toto2
tutu
********
toto3
tete
********

Je veux arriver a ca :

*******
toto1
totoajouté
titi
*******
toto2
totoajouté
tutu
********
(...)

Le probleme est que je ne connais pas a l'avance le nombre de partie entre lignes (******)
et mes connaissances en awk sont très basiques.
Je peux le faire en fortran, mais je trouve que awk est quand meme plus elegant et efficace dans une chaine en shell.

merci pour votre aide, et desole pour le niveau de la question!
Configuration: Linux
Firefox 3.5.5

7 réponses

  1. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    hello
    $ cat a1
    ********
    toto1
    titi
    ********
    toto2
    tutu
    ********
    toto3
    tete
    ******** 
    $ awk '{print $0} ; /^toto/ {print "totoajoute"}' < a1
    ********
    toto1
    totoajoute
    titi
    ********
    toto2
    totoajoute
    tutu
    ********
    toto3
    totoajoute
    tete
    ******** 
    $ 
    
    0
    1. matthieu
       
      merci dubcek pour ta reponse si rapide.
      En fait, en voulant simplifier mon exemple, j'ai introduit un cas particulier.
      Le nombre de ligne entre les ******** est toujours le meme, mais les champs peuvent etre differents (pas tous des "toto..." )
      il s'agit pour etre precis de nom de substance (ex :

      ****
      nitrate
      .true.
      0.0
      *****
      phosphate
      .false.
      0.0
      *****

      (...)

      qui doit devenir par exemple

      ****
      nitrate
      nitrate
      .true.
      0.0
      *****
      (...)


      Je pensais d'abord compter le nombre de substances (nb de lignees contenant **** -1)
      puis faire une boucle a partir de la premiere occurence de "*****" (attention la ligne peut faire 20 "*")
      je vois a peu pres comment faire, mais ce sont les "mots" qui me manquent !
      desole pour cette mauvaise explication initiale

      merci encore pour votre aide
      0
  2. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    après toute ligne qui commence par 3 *, on lit la suivante et on l'imprime 2 fois
    $ cat a1
    ****
    nitrate
    .true.
    0.0
    *****
    phosphate
    .false.
    0.0
    *****
    choucroute
    .true.
    1.1
    
    $ awk '{print $0} ; /^\*\*\*/ {getline ; print $0 ; print $0}' < a1
    ****
    nitrate
    nitrate
    .true.
    0.0
    *****
    phosphate
    phosphate
    .false.
    0.0
    *****
    choucroute
    choucroute
    .true.
    1.1
    
    0
    1. matthieu
       
      haha, merci pour la choucroute dubcek, on y est presque (faut etre patient avec les newb')
      Quand on veut simplifier son probleme pour etre lu, on rajoute d'autre soucis

      En fait,
      je dois recopier nitrate, mais aussi rajouter 0.0 dans la 5eme ligne par exemple
      (certains elements sont recopies, d'autres sont inseres)

      ****
      nitrate
      .true.
      0.0
      *****
      (...)

      doit donner (en resume)


      ****
      nitrate
      nitrate
      .true.
      .true.
      0.0
      1000.
      *****
      (...)


      Ton script marche pour la premiere ligne apres ***, mais pour une autre ?
      la commande getline est un peu obscure pour moi.

      Merci de ton temps deja passe, je vais essayer de bidouiller a partir de tes infos, et la doc awk (c'est velu quand meme!)
      0
  3. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    getline lit la ligne suivante, je peux faire:
     awk '{print $0} ; /^\*\*\*/ {getline ; print $0 "\n" $0 ; getline ; print $0 "\n" $0 "\n" "99.0" }' < a1
    ****
    nitrate
    nitrate
    .true.
    .true.
    99.0
    0.0
    *****
    phosphate
    phosphate
    .false.
    .false.
    99.0
    0.0
    *****
    
    0
  4. matthieu
     
    merci encore pour ta reactivite et ta patience (vu la clarte de mon expose)
    Reste un dernier point que je vais essayer de corriger, vu tout ce que tu m'a donne

    le fichier d'entree se termine par :

    (...)
    blabla
    *************

    et je voudrai qu'il se termine de la meme facon une fois reecrit, en fait que le script awk ne s'applique pas a la derniere occurence de ***** (sinon il recopie les blancs encore apres). C'est possible?
    Je pensais supprimer les x dernieres lignes (toujours avec awk, une fois le script execute)

    Quoiqu'il en soit, merci beaucoup, avec ca je me debrouillerai (j'allais partir dans des boucles for...!)
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    il faut connaitre le nombre de lignes et on teste, si il y a égalité avec la ligne courante (NR) on sort

    $ L=$(wc -l < a1)
    $ awk '{print $0} ; /^\*\*\*/ {getline ; if (NR == '"$L"') exit ; print $0 "\n" $0 ; getline ; print $0 "\n" $0 "\n" "99.0" }' < a1
    ****
    nitrate
    nitrate
    .true.
    .true.
    99.0
    0.0
    *****
    phosphate
    phosphate
    .false.
    .false.
    99.0
    0.0
    *****
    $ 
    
    0
  7. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Salut,

    Et avec "sed" (désolé dubcek ;-)) ) :

    jp@MDK:~/tmpfs ssh$ cat fich
    ****
    nitrate
    .true.
    0.0
    *****
    phosphate
    .false.
    0.0
    *****
    choucroute
    .true.
    1.1
    
    
    jp@MDK:~/tmpfs ssh$ sed -i.bak '/\*\+/{n;/^$/q;s/.*/&\n&/;n;s/.*/&\n&\n99.0/}' fich
    
    jp@MDK:~/tmpfs ssh$ cat fich
    ****
    nitrate
    nitrate
    .true.
    .true.
    99.0
    0.0
    *****
    phosphate
    phosphate
    .false.
    .false.
    99.0
    0.0
    *****
    choucroute
    choucroute
    .true.
    .true.
    99.0
    1.1
    
    
    jp@MDK:~/tmpfs ssh$

    ;-))
    0
    1. matthieu
       
      merci a tous les deux, j'en ai assez pour m'en sortir !
      Je vais essayer sed (pour le style), mais je trouve que pour un debutant comme moi, awk reste un peu plus comprehensible ! quoique on voit des similutudes dans la syntaxe.
      Je ferme le sujet et merci pour tout
      0
  8. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    on a pas besoin de compter les lignes, getline retourne 0 en cas d'eof
      $ awk '{print $0} ; /^\*\*\*/ {if(getline == 0) exit ; print $0 "\n" $0 ; getline ; print $0 "\n" $0 "\n" "99.0" }' < a1
    0
    1. matthieu
       
      tout reste dans le meme script encore mieux pour pas charger les scripts de lancement !
      thanks again
      0