#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