pb script ksh

pb script ksh - Shell/Batch - Programmation

Marsh Posté le 01-09-2006 à 08:53:24    

   
     Bonjour, j'espere que vous pourrez m'aider.
 
Voila ci dessous mon petit script, mais le fait et qu'en resultat je devrais avoir un chiffre qui est 1630 mais à la place il met met 0 et j'ai passé 2h dessus sans savoir pourquoi, si quelqu'un sait mon erreur.
 
Merci de votre aide
 
 

Citation :

#!/bin/ksh
 
typeset -i tot_mts_int=0
typeset -i tot_mts_adm=0
typeset -i tot_final=0
 
mts=mts1.csv
rm $mts
touch $mts
total_port=total1.csv
rm $total_port
touch $total_port
 
cat INVENTAIRE.csv | grep -i mon >$mts
 
cat $mts |while read LIGNE
do
 
    set $LIGNE
    tot_mts_int=$(($tot_mts_int+$5))
    tot_mts_adm=$(($tot_mts_adm+$7))
    tot_final=$(($tot_mts_int)-($tot_mts_adm))
     
done
 
echo "Nbres Int MTS" >$total_port
echo "${tot_final}" >>$total_port

Reply

Marsh Posté le 01-09-2006 à 08:53:24   

Reply

Marsh Posté le 01-09-2006 à 17:58:49    

suya95 a écrit :

Bonjour, j'espere que vous pourrez m'aider.
 
Voila ci dessous mon petit script, mais le fait et qu'en resultat je devrais avoir un chiffre qui est 1630 mais à la place il met met 0 et j'ai passé 2h dessus sans savoir pourquoi, si quelqu'un sait mon erreur.
 
Merci de votre aide
 
 

Citation :

#!/bin/ksh
 
typeset -i tot_mts_int=0
typeset -i tot_mts_adm=0
typeset -i tot_final=0
 
mts=mts1.csv
rm $mts
touch $mts
total_port=total1.csv
rm $total_port
touch $total_port
 
cat INVENTAIRE.csv | grep -i mon >$mts
 
cat $mts |while read LIGNE
do
 
    set $LIGNE
    tot_mts_int=$(($tot_mts_int+$5))
    tot_mts_adm=$(($tot_mts_adm+$7))
    tot_final=$(($tot_mts_int)-($tot_mts_adm))
     
done
 
echo "Nbres Int MTS" >$total_port
echo "${tot_final}" >>$total_port



 
 
Déjà, dans ce type de travail, tu peux remplacer

cat INVENTAIRE.csv | grep -i mon >$mts


par

grep -i mon INVENTAIRE.csv >$mts


car le grep peut aussi bien traiter l'entrée standard qu'un fichier passé en paramètre
 
Par ailleurs, tu peux éviter le fichier temporaire en mettant directement

grep -i mon INVENTAIRE.csv |while read ligne


Hé oui, si le read peut lire des infos venant d'un "cat", il peut aussi lire des infos venant d'un "grep". Mais cela ne résoudra pas ton pb...
 
Petite question rapide: est-ce que "$ligne" contient bien des valeurs séparées par un espace ou une tabulation et que "$5" et "$7" sont bien des nombres ??? Parce que si le séparateur est autre chose (style point-virgule), le "set" ne découpera rien et mettra tout dans $1 donc $5 et $7 seront égaux à 0 dont tes totaux seront aussi à 0 en fin de boucle !!!
 
Sinon, une remarque générale qui s'applique au Bourne Shell et Bourne Again Shell (elle ne s'applique pas au ksh mais c'est pour la portabilité)
 
En shell de base (Bourne et associés), le pb de cette structure "cat machin |while read ...", c'est que le pipe te génére un sous-processus dans lequel tes variables sont bien remplies mais perdues à la fin du done. Tu peux en avoir la preuve si tu mets un "echo" dans ta boucle !!!
Et inutile d'essayer avec "export". Je l'ai déjà fait et ça marche pas car le "export" sert à rendre visible une variable depuis un père vers un fils, alors que ton script initial cherche à faire remonter des variables depuis un fils vers son père...
 
Donc en shell de base, tu as 2 solutions pour résoudre le pb (qui fonctionnent aussi en ksh)
1) tu utilises des parenthèses pour grouper le while et le echo final dans le même processus

cat $mts | ( while read ligne
    do
        <... calcul et opérations ...>
    done
 
    # Grace à la parenthèse on reste dans le même processus
    echo $les resultats >fichier_resultat
)
# Ici, on n'est plus dans le même processus - Toutes les variables sont perdues


 
2) tu t'arranges pour ne pas avoir de pipe. Par exemple, pour lire un fichier, tu peux le stocker dans un canal numéroté que tu liras ensuite quand tu en auras envie, style


# Stockage du fichier dans le canal n° 3 (0, 1 et 2 étant déjà utilisés)
exec 3<$mts
 
# Lecture du canal n° 3 ligne par ligne
while read ligne 0<&3
do
 <... calcul et opérations ...>
done
 
# Pas de pipe donc pas de processus différent
echo $les resultats >fichier_resultat


 
La solution 2 est parfaite pour lire un fichier. Malheureusement, elle ne te permettra pas de lire une commande du style

commande_quelconque | while read ligne
do
    <...>
done


Ou alors il te faudra créer un fichier temporaire contenant le résultat de "commande_quelconque" (ce que tu avais fait avec "grep ... >$mts" ) que tu pourras ensuite stocker dans un canal numéroté pour le lire...


Message édité par Sve@r le 01-09-2006 à 18:25:15

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 02-09-2006 à 15:09:12    

Au lieu de faire :

cat $mts| while read LIGNE
do
  . . .
done

il vaut mieux :

while read LIGNE
do
  . . .
done < $mts


On utilise un process de moins, et de plus les modifications de variables effectuées dans la bouche while ne sont pas perdues.
 
 
Il est possible de lire plusieurs variables avec l'instruction read :

while read mts_1 mts_2 mts_3 mts_4 mts_int mts_6 mts_adm _mts_8
do
    (( tot_mts_int=tot_mts_int+mts_int ))  
    (( tot_mts_adm=tot_mts_adm+mts_adm ))  
    (( tot_final=tot_mts_int-tot_mts_adm ))  
done < $mts


Si le séparateur de champ n'est pas l'espace, on peut le spécifier sur la commande read, par exemple pour le séparateur ';' :

IFS=';' read field1 field2


 
Une autre technique pour lire le fichier et faite les cumuls :

awk '
   tolower($0) ~ /mon/ {
      int += $5;
      adm += $7;
   }
   END {
      print int, adm, int-adm
   } ' < $mts | read tot_mts_int tot_mts_adm tot_final


 
Jean-Pierre.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed