Calcul sur des colonnes dans le shell

Résolu
sheol -  
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   -
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.
Configuration: Linux Fedora
Firefox 2.0.0.10

8 réponses

  1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    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
  2. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 659
     
    hello
    avec awk:
    awk '{if (x[$1] == 0) x[$1]=$2 else printf("%d %6.3f\n", $1, x[$1] - $2)}' < fichier.txt
    0
    1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
       
      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
  3. sheol
     
    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
    1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
       
      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
  4. sheol Messages postés 6 Statut Membre 2
     
    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
  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 659
     
    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
    1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
       
      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
  7. sheol Messages postés 6 Statut Membre 2
     
    ç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
  8. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    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
  9. sheol Messages postés 6 Statut Membre 2
     
    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
    1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
       
      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