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 06/06/2012, à 21:43

Swiss_Knight

[OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Salut,

j'ai un souci, je ne maîtrise pas awk ni sed et j'ai besoin de rapatrier les deux dernières lignes de fichiers texte à la fin de la deuxième ligne dudit fichier.

Exemple très simplifié :
un deux A1 A2 B
290 0.982
380 0.434
385 0.251
445 0.338
5.59 2.22
1.23

doit devenir :
un deux A1 A2 B
290 0.9825.59 2.22 1.23
380 0.434
385 0.251
445 0.338

contraintes :
Dans la 1ère ligne ce sont des entêtes et il peut y avoir un nombre variable de "A" (ici il y a A1 et A2 mais il peut y en avoir plus) Le nombre de champs dans l'avant dernière ligne correspond aux valeurs des A. Il y a donc autant de champs dans cette ligne qu'il y a de A en entête. Ici il y en a deux. Mais s'il y avait 5 A il y en aurait 5.
La dernière ligne correspond à la variable B.
Les 4 lignes 2 à 5 peuvent aussi être plus nombreuses, mais ce sera toujours les deux dernières lignes du fichier que je veux mettre à la suite de la deuxième ligne, pour que ça soit sous les entêtes des variables A et B en fait.
Bonus; si au lieu des espaces entre les champs, il pouvait y avoir une virgule, suivie d'une espace, ce serait top.

On m'a proposé ceci sur un autre forum :

ed -s fichier.txt <<<$'$-1s/^/ /\n$s/^/ /\n$-1,$j\n$m2\n2,3j\n,p'

le problème c'est que j'aimerai que ceci soit effectué sur tous les fichiers présent dans un dossier, et ce en une seule commande.
J'ai essayé avec awk mais je n'arrive à rien tout seul encore :S

Merci de vos tuyaux ! ; )

Dernière modification par Swiss_Knight (Le 07/06/2012, à 21:59)


xuniL

Hors ligne

#2 Le 06/06/2012, à 22:44

pingouinux

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Bonsoir,

Le script :

$ cat x.sh
#!/bin/bash

rep="$1"
modif() {
   fic="$1"
   deb=$(head -2 "$fic")
   mil=$(sed -n '3,$p' "$fic" | head -n-2)
   fin=$(tail -2 "$fic")

   echo -e "$deb "$fin"\n$mil" >"$fic.modif"
}

for i in "$rep"/*; do modif "$i"; done

Mode d'emploi :

./x.sh repertoire_qui_contient_les_fichiers

Pour chaque fichier fic, génère un fichier fic.modif
Pour les virgules, si tu pouvais donner un exemple de ce que tu veux obtenir…

Dernière modification par pingouinux (Le 06/06/2012, à 22:59)

Hors ligne

#3 Le 06/06/2012, à 23:11

Swiss_Knight

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Salut pingouinux et merci pour ta réponse qui apparemment marche très bien...
Sauf que j'ai pas vu que fallait enregistrer ça dans un  fichier et j'ai lancé direct en console : le système s'est mis à freezer méchamment, rien de grave j'espère :S ....

ça me permet aussi de préciser un peu mieux mon problème : c'est une commande que je dois lancer via un autre logiciel, donc il faudrait que ça puisse tenir en une commande, et que ça ne fasse pas appel à un fichier externe, ce qui m'évitera de me trimballer plusieurs fichier avec mon fichier de script principal de mon autre logiciel. J'aimerai qu'il puisse faire tout à lui tout seul en passant des commandes au système. J'arrive encore assez bien à enlever certaines lignes et faire des arrangements simples avec sed mais pour le problème ici, je sèche et je ne vois pas comment réduire ce script à une ligne qui tourne d'elle même...

Et une dernier truc ; c'est qu'il faudrait que ça puisse écrire par dessus le fichier de base.

Dernière modification par Swiss_Knight (Le 06/06/2012, à 23:22)


xuniL

Hors ligne

#4 Le 06/06/2012, à 23:35

Postmortem

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Salut,
Un "petit" awk (qui m'a fait mal à la tête !) :

awk 'BEGIN {OFS=","}
   FNR == 1 { if( i==1 ) {
                 ligne[2]=ligne[2] OFS ligne[nb_lignes-1] OFS ligne[nb_lignes]
                 for(i=1; i<=nb_lignes-2; i++) { gsub(" ",",",ligne[i])
                       print ligne[i] > nom_fic
                 }
              }; i=0; nom_fic=FILENAME
            }
       { ligne[FNR]=$0; nb_lignes=FNR; i=1 }
   END { ligne[2]=ligne[2] OFS ligne[FNR-1] OFS ligne[FNR]
         for(i=1; i<=FNR-2; i++) { gsub(" ",",",ligne[i]); print ligne[i] > nom_fic}}' *.txt

Edit : en un peu plus court :

awk 'BEGIN {OFS=","}
   FNR == 1 { if( j==1 ) {
                 ligne[2]=ligne[2] OFS ligne[nb_lignes-1] OFS ligne[nb_lignes]
                 for(i=1; i<=nb_lignes-2; i++) print ligne[i] > nom_fic }
              nom_fic=FILENAME
            }
       { ligne[FNR]=$0; gsub(" ",",",ligne[FNR]); nb_lignes=FNR; j=1 }
   END { ligne[2]=ligne[2] OFS ligne[nb_lignes-1] OFS ligne[nb_lignes]
         for(i=1; i<=FNR-2; i++) print ligne[i] > nom_fic }' *.txt

Re-Edit n° $X : en plus plus court (enfin pas tant que ça !) et avec les champs séparés par virgule suivie d'une espace :

awk ' function affiche()
      {
         ligne[2]=ligne[2] ", " ligne[nb_lignes-1] ", " ligne[nb_lignes]
         for(i=1; i<=nb_lignes-2; i++) print ligne[i] > nom_fic
      }
      FNR == 1 { if( j==1 ) affiche(); nom_fic=FILENAME; j=1 }
      { ligne[FNR]=$0; gsub(" ",", ",ligne[FNR]); nb_lignes=FNR }
      END { affiche() }' *.txt

Dernière modification par Postmortem (Le 07/06/2012, à 00:18)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#5 Le 07/06/2012, à 05:39

pingouinux

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Voici mon script du #2, modifié pour remplacer tous les séparateurs de champs par ", ", et pour réécrire sur le fichier d'origine (peut-être dangereux en cas d'erreur lors du lancement de la commande).

$ cat x.sh
#!/bin/bash

rep="$1"
modif() {
   fic="$1"
   deb=$(head -2 "$fic")
   mil=$(sed -n '3,$p' "$fic" | head -n-2)
   fin=$(tail -2 "$fic")

   echo -e "$deb "$fin"\n$mil" | sed 's/  */, /g' >"$fic.modif.$$"
   mv "$fic.modif.$$" "$fic"
}

for i in "$rep"/*; do modif "$i"; done

Hors ligne

#6 Le 07/06/2012, à 21:10

Swiss_Knight

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Salut et merci pour vos messages !

est-ce que ça peut tenir en une ligne sans passer par un fichier qui contient le script .... ?
et est-ce possible de cibler un répertoire, peu importe où on se trouve dans l'arborescence du système ?

Bonne fin de soirée !


xuniL

Hors ligne

#7 Le 07/06/2012, à 21:40

Postmortem

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

La dernière commande que j'ai mise (oui, il s'agit bien d'une seule commande !) peut etre exécutée directement dans le terminal.
Pour cibler les fichiers de n'importe quel repertoire, il suffit de remplacer *.txt par /chemin/vers/fichiers/*.txt par exemple.


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#8 Le 07/06/2012, à 21:49

Swiss_Knight

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Donc ceci devrait fonctionner :

awk ' function affiche() { ligne[2]=ligne[2] ", " ligne[nb_lignes-1] ", " ligne[nb_lignes] for(i=1; i<=nb_lignes-2; i++) print ligne[i] > nom_fic } FNR == 1 { if( j==1 ) affiche(); nom_fic=FILENAME; j=1 } { ligne[FNR]=$0; gsub(" ",", ",ligne[FNR]); nb_lignes=FNR } END { affiche() }' /chemin/vers/fichiers/*.txt

J'essaye de suite alors : j'ai une "syntax error"

Je reviens parce que j'ai eu le droit à une solution différente ailleurs et qui fonctionne bien dans ma situation, je la mets ici :

awk 'BEGIN{for (n=1;n<ARGC;n++){f=ARGV[n]; i=0;while("cat " f | getline)x[++i]=$0 ; print x[1] "\n" x[2], x[i-1], x[i] > f ".2" ; for (m=3;m<i-1;)print x[m++]> f ".2"}}'  /chemin/vers/fichiers/*.txt 

Dernière modification par Swiss_Knight (Le 07/06/2012, à 21:58)


xuniL

Hors ligne

#9 Le 07/06/2012, à 21:59

Postmortem

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Il faut quand meme respecter les retour à la ligne ! Une meme commande peut etre sur plusieurs lignes.

Édit :
Et selon ta version de awk, ça peut ne pas fonctionner. Faut essayer avec gawk à la place.

Dernière modification par Postmortem (Le 07/06/2012, à 22:06)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#10 Le 07/06/2012, à 23:17

Swiss_Knight

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Ok, le problème c'est que je lance cette commande via octave et que je vois très mal comment lui dire "ça c'est un saut de ligne"...

pour la version de awk :

$ awk --version
GNU Awk 3.1.6
Copyright © 1998, 1991-2007 Free Software Foundation, Inc.

mais je pige pas, parce que si je fais :

$ gawk --version
GNU Awk 3.1.6
Copyright © 1998, 1991-2007 Free Software Foundation, Inc.

ben j'ai strictement la même chose... je ne comprends pas bien.


xuniL

Hors ligne

#11 Le 08/06/2012, à 07:54

Postmortem

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Bonjour !
Ton awk est un alias de gawk, y'a pas de soucis avec ça, c'est bien comme ça.
Octave, je ne connais pas.
Je réessaierai ma commande plus tard, j'ai peut-être fait une erreur. Et je vais aussi tester l'autre solution que tu as donnée histoire d'essayer de comprendre comment elle fonctionne!


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#12 Le 08/06/2012, à 08:25

pingouinux

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Salut,
Pour que cette commande de Postmortem fonctionne, lorsqu'elle est regroupée en une seule ligne, il y a juste un ";" à ajouter :

awk ' function affiche() { ligne[2]=ligne[2] ", " ligne[nb_lignes-1] ", " ligne[nb_lignes] for(i=1; i<=nb_lignes-2; i++) print ligne[i] > nom_fic } FNR == 1 { if( j==1 ) affiche(); nom_fic=FILENAME; j=1 } { ligne[FNR]=$0; gsub(" ",", ",ligne[FNR]); nb_lignes=FNR } END { affiche() }' /chemin/vers/fichiers/*.txt
awk ' function affiche() { ligne[2]=ligne[2] ", " ligne[nb_lignes-1] ", " ligne[nb_lignes]; for……………
                                                                                          ^
                                                                                          |
                                                                                         ici

Hors ligne

#13 Le 08/06/2012, à 15:33

Postmortem

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Merci pingouinux ! C'est cool, même plus besoin de chercher ses erreur quand t'es là !


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#14 Le 08/06/2012, à 15:45

pingouinux

Re : [OK][awk,sed,?] Déplacer les champs des 2 dernières lignes sur la 2ème

Salut Postmortem,
Ton code était bon. C'est juste la transcription sur une ligne qui a été faite un peu vite…

Hors ligne