Calcul sur des colonnes dans le shell

Résolu/Fermé
sheol - 7 janv. 2008 à 18:27
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 - 9 janv. 2008 à 22:49
Bonjour,

J'ai un soucis !
Cela fait plusieurs jours (... Je sais je suis nul) que j'essaye de faire la chose suivante :
J'ai un fichier qui se présente comme cela :
1 5.178
2 5.178
3 2.982
4 2.982
5 2.882
6 2.881
7 2.881
8 2.882
1 3.016
2 3.016
3 2.993
4 2.993
5 3.033
6 3.034
7 3.034
8 3.034


Sachant que 8 est en fait une variable (ça peut etre un autre nombre, c'est pris dans un fichier).
Ce dont j'ai besoin, c'est de manipuler ces fichiers de telle sorte qu'en sortie j'ai :
1 2.162 # soit `5.178-3.016`
2 2.162
3 -.011 # soit 2.982-2.993
4 xxx
5 xxx
6 xxx
7 xxx
8 xxx

Pour chaque valeur de i allant de 1 à $NombredAtomes (ici $NombredAtomes=8 ), j'ai besoin qu'il m'affiche la différence entre la première et la deuxième apparition du nombre à coté de i.

J'espère que c'est assez clair ...

C'est en fait des valeurs de spin électronique pour des boites de $NombredAtomes atomes. Et j'ai besoin qu'il me fasse spinup - spindown pour chacun de ces atomes.

Voilivoila !

Déjà merci de m'avoir lu jusqu'ici :), même si vous n'avez pas la réponse.
A voir également:

8 réponses

jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
7 janv. 2008 à 19:39
Salut,
[tmpfs]$ cat fich.txt
1 5.178
2 5.178
3 2.982
4 2.982
5 2.882
6 2.881
7 2.881
8 2.882
1 3.016
2 3.016
3 2.993
4 2.993
5 3.033
6 3.034
7 3.034
8 3.034

[tmpfs]$ cat foo.sh

#! /bin/bash

#set -x

nbre=$1
nbre2=$((nbre+1))

A=( $(sed -ne "1,$nbre s/.[^ ]*//p" fich.txt | sed ':b;N;$! bb;s/\n/ /g') )
B=( $(sed -ne "$nbre2,$ s/.[^ ]*//p" fich.txt | sed ':b;N;$! bb;s/\n/ /g') )

i=0
while [ "$i" -le "$((nbre-1))" ]
do
echo -e "$((i+1)) \c" && echo "${A[$i]} - ${B[$i]}" | bc
i=$((i+1))
done

[tmpfs]$ ./foo.sh 8
1 2.162
2 2.162
3 -.011
4 -.011
5 -.151
6 -.153
7 -.153
8 -.152

[tmpfs]$
:-))
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
8 janv. 2008 à 12:53
hello
avec awk:
awk '{if (x[$1] == 0) x[$1]=$2 else printf("%d %6.3f\n", $1, x[$1] - $2)}' < fichier.txt
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
8 janv. 2008 à 13:11
Pffffffffff, tu pouvais pas le dire avant toi aussi, me serai moins fait...













































... suer ;-DDDDDD

Merci ;-)

Édit : Il manque un point virgule avant le "else", et le résultat n'est pas tout à fait celui escompté ;-((
0
merci !!!!

jipicy, ta méthode marche super bien !
Par contre dubcek je ne sais pas pourquoi ça ne marche pas chez moi. Je n'ai pas les connaissances en awk suffisantes pour corriger ce qui doit etre une simple erreur de synthaxe surement, mais il me marque qu'il y a une "synthax error" au niveau du "else" dans ton script awk.

En tous cas merci bien à tous les deux.
dubcek si tu vois ta faute je veux bien que tu nous en fasses part s'il te plait comme ça j'apprendrais des choses en awk ! :)

+++
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
8 janv. 2008 à 15:09
En ce qui concerne l'erreur du "else" je l'ai noté dans l'édition de mon précédent message, il suffit de rajouter un point virgule avant le "else" :
awk '{if (x[$1] == 0) x[$1]=$2 ; else printf("%d %6.3f\n", $1, x[$1] - $2)}' < fichier.txt
Par contre le résultat n'est pas celui attendu ;-(( :
1  2,000
2  2,000
3  0,000
4  0,000
5 -1,000
6 -1,000
7 -1,000
8 -1,000
???
0
sheol Messages postés 6 Date d'inscription mardi 8 janvier 2008 Statut Membre Dernière intervention 11 janvier 2008 2
8 janv. 2008 à 15:24
pardon! je répondais au message à partir du mail envoyé par le site ... à l'époque de ton premier post.
Je n'avais donc pas connaissance de ton edit.

En tous cas le résultat est bizarre ! c'est comme s'il travaillait sur des entiers uniquement.

NB: je me suis inscrit :) :P
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
8 janv. 2008 à 15:30
effectivement, il manque un ; quand tout est sur la même ligne ,mais j'ai bien les décimales, mais j'utilise gawk.

C:\>gawk '{if (x[$1] == 0) x[$1]=$2 ; else printf("%d %6.3f\n", $1, x[$1] - $2)}' < g1.txt
1 2.162
2 2.162
3 -0.011
4 -0.011
5 -0.151
6 -0.153
7 -0.153
8 -0.152

ca serait pas un problème de . ou de , comme séparateur décimal ?
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
8 janv. 2008 à 15:37
ca serait pas un problème de . ou de , comme séparateur décimal ?
Si effectivement, en remplaçant les points par de virgules ça roule ;-))

Merci bien.
0
sheol Messages postés 6 Date d'inscription mardi 8 janvier 2008 Statut Membre Dernière intervention 11 janvier 2008 2
8 janv. 2008 à 15:33
ça marche parfaitement avec chez moi.

Pourquoi foo.sh ne fonctionne plus quand je l'intègre dans mon script ça me marque une erreur à la ligne :

B=( $(sed -ne "$nbre2,$ s/.[^ ]*//p" SpinUpDownList.tmp | sed ':b;N;$! bb;s/\n/ /g') )


mon script entier :

#/usr/bin/bash

echo "Which file ?"
read file
NumberOfAtoms=`grep NumberOfAtoms ${file} |sed s/NumberOfAtoms//g`
NumberOfSpecies=`grep NumberOfSpecies ${file}|sed s/NumberOfSpecies//g`

rm FullUpDownList.tmp

NumberOfLinesToGrep=$((1+10*${NumberOfSpecies}+4+4*${NumberOfAtoms}+5))
egrep -B${NumberOfLinesToGrep} Relaxed ${file} | egrep -v "[yz]2|orb|MB|scaled|Qtot|Cr|Fe" | sed /^$/d  | sed /^...........................$/d | cut -d ' ' -f -6 | cut -d ' ' -f 4- | sed /^$/d  > FullUpDownList.tmp

nbre=$NumberOfAtoms
nbre2=$((NumberOfAtoms+1))

A=( $(sed -ne "1,$nbre s/.[^ ]*//p" FullUpDownList.tmp | sed ':b;N;$! bb;s/\n/ /g') )
B=( $(sed -ne "$nbre2,$ s/.[^ ]*//p" FullUpDownList.tmp | sed ':b;N;$! bb;s/\n/ /g') )

i=0
while [ "$i" -le "$((nbre-1))" ]
do
echo -e "$((i+1)) \c" && echo "${A[$i]} - ${B[$i]}" | bc >>
i=$((i+1))
done
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
8 janv. 2008 à 15:48
Ben là c'est difficile à dire ;-\

Exécute ton script en mode débogage (set -x) peut être que l'erreur sera plus parlante...

Sinon le fichier en entrée (FullUpDownList.tmp) est-il vraiment comparable à l'exemple fourni dans ton 1er post ?
0
sheol Messages postés 6 Date d'inscription mardi 8 janvier 2008 Statut Membre Dernière intervention 11 janvier 2008 2
9 janv. 2008 à 22:15
Re-bonjour !

En effet mon fichier FullUpDownList.tmp est exactement le même que l'exemple fourni dans mon premier post.

J'ai décidé, pour faire plus simple, d'apprendre le Perl. Ca fait une demi journée que je m'y suis mis et déjà je fais des choses que j'avais beaucoup de mal à faire en BASH scripts donc je suis vraiment content.

J'ai d'ailleurs déjà un petit soucis mais je vais ouvrir un nouveau topic. Merci à tous pour vos réponses !!!
C'est vraiment très cool.

+++++++++++++ sur d'autres topics ! :)
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
9 janv. 2008 à 22:49
Dommage ;-((

Mais autant te le dire, Perl c'est un truc pour faignants et le plus grand d'entre eux ne devrait pas tarder à ce manifester sur ton post ;-DDD
0