IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Écrire le résultat d'une boucle sur une ligne


Sujet :

Shell et commandes GNU

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 162
    Points : 66
    Points
    66
    Par défaut Écrire le résultat d'une boucle sur une ligne
    Bonjour,

    Je récupère des données provenant de plusieurs fichiers ayant tous la même forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    toto-1.6-1.6.out toto-1.6-1.7.out .......toto-2.5-2.5.out
    de la façon suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    for (( i=0 ; $i <= 15 ; i++ ))
    do
            d1=$(echo "1.6 + $i * 0.1" | bc )
     
            for (( j=0 ; j <= 15 ; j++ ))
            do
                    d2=$(echo "1.6 + $j * 0.1" | bc )
                    if [ -f toto-$d1-$d2.out* ] ;then 
                    energy[$i_$j]=$(grep 'tutt' toto-$d1-$d2.out* | awk 'NR = 1 {print $5}' )  #recuperation de la valeur de l energie
                    energy[$i_$j]=$( echo "( $Somme_ref -  ${energy[$i_$j]})* 627.509 " |bc )  # calcul de l energie en kcal
                    #echo "${energy[$i_$j]}"
                    else 
                    energy[$i_$j]=$(echo "--" )
                    #echo "${energy[$i_$j]}"
                    fi
            done
    done
    En quelque sorte, j'ai un tableau à deux dimensions.

    Ce que je voudrais faire c'est écrire le résultat de la façon suivante :
    valeur de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    1.6_1.6  1.6_1.7 .....1.6_2.5
    1.7_1.6  1.7_1.7 .....
    ......
    2.5_1.6
    Comme je veux pas tout changer si j'ai un tableau de dimension différentes, je veux éviter un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    echo "${energy[1_1]} ${energy[1_2]}  ${energy[1_3]}   ${energy[1_4]}   " >> tutu
    echo "${energy[2_1]} ${energy[2_2]}  ${energy[2_3]}   ${energy[2_4]}   " >> tutu
    echo "${energy[3_1]} ${energy[3_2]}  ${energy[3_3]}   ${energy[3_4]}   " >> tutu


    J'avais pensé à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for (( i=0 ; $i <= 15 ; i++ ))
    do
            for (( j=0 ; j <= 15 ; j++ ))
            do
     
        echo "${energy[$i_$j]}" >> tutu
     
            done
    done
    Mais ça va me produire une suite de ligne.
    Alors comment faire ?
    Faut il produire des colonnes que l'on place les unes à côté des autres si oui comment faire ? Ou faut il produire une suite de ligne et là aussi comment faire ?

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 587
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 587
    Points : 19 468
    Points
    19 468
    Par défaut
    Bonjour,

    Quel interpréteur de commandes as-tu l'intention d'utiliser ?
    SH n'a pas de tableaux associatifs, or tableau[${var1}_${var2}] est un tableau associatif, qui doit faire l'objet d'une déclaration explicite.
    mais je ne vois pas bien l'utilité de tels tableaux...

    il y a plusieurs erreurs en plus dans ton script :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if [ -f toto-$d1-$d2.out* ] ;then

    est-ce une coquille, ou testes-tu l'existence de plusieurs fichiers ?
    entre [ ] et avec test, les variables doivent être entre guillemets.

    sans être une erreur, grep | awk est maladroit, autant n'utiliser que awk.
    les tests d'égalité dans awk, c'est var == var1.

    enfin, pour répondre à ta question, utilise printf, ou echo -n.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 162
    Points : 66
    Points
    66
    Par défaut
    Alors, j'ai pas compris grand chose. J'ai jamais suivit de cours de programmation, j'apprends sur le tas ce qui n'est pas la meilleure méthode ! Mais mon but c'est d'automatiser des routines le plus rapidement possible si c'est propre et optimisé c'est un plus, mais c'est pas vital non plus.

    J'utilise bash comme interpréteur. Je sais qu'il ne gère pas les tableaux mais avec energy[$i_$j] je peux récupérer toutes mes valeurs dans des variables séparées de manière sur. Je vois pas comment faire différemment en bash.
    Ensuite mon test, oui je test l'existence du fichier et ça marche très bien, mais peut être pour de mauvaise raison ! Je comprends pas bien le sens de cette phrase :
    entre [ ] et avec test, les variables doivent être entre guillemets.
    c'est quoi test une commande à écrire ou le -f entre les crochets.

    Ensuite j'ai cherché pour coupler n'utiliser que awk, mais
    1) j'ai pas réussi à l'utiliser,
    2) je vois pas comment ne prendre que la première sortie de la recherche

    Et pour conclure il va falloir écrire la sortie comme ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for (( i=0 ; $i <= 15 ; i++ ))
    do
            for (( j=0 ; j <= 15 ; j++ ))
            do
     
        echo -n "${energy[$i_$j]}" >> tutu
     
            done
     echo " " >> tutu
    done
    écrit comme ça il ne renvois pas a la ligne pour la boucle j mais à chaque fin de boucle i il effectue un renvois à la ligne pour la prochaine boucle j ?

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 721
    Points : 31 044
    Points
    31 044
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Erlen Voir le message
    Ensuite mon test, oui je test l'existence du fichier et ça marche très bien, mais peut être pour de mauvaise raison !
    La syntaxe [ -f fichier ] n'est appliquable que sur un seul fichier. Tu ne peux pas écrire [ -f fic1 fic2 fic3 ] car le shell ne comprendra pas ce que tu veux lui dire.
    Tu peux éventuellement tester d'un coup plusieurs fichiers mais en respectant les règles d'écritures des expressions logiques et en utilisant des connecteurs "and" et/ou "or" pour affiner ton expression
    Exemple
    [ -f fic1 -o -f fic2 -o -f fic3 ] renverra vrai si l'un des trois est un fichier
    [ -f fic1 -a -f fic2 -a -f fic3 ] renverra vrai si les trois sont des fichiers

    Citation Envoyé par Erlen Voir le message
    Je comprends pas bien le sens de cette phrase : entre [ ] et avec test, les variables doivent être entre guillemets.
    Quand on manipule des variables, il faut explicitement les encadrer de guillemets. Cela permet au shell de comprendre qu'il y a quand-même quelque chose même si la variable est vide
    Exemple: [ -f $var ]: le problème ici est que si $var est vide, le shell verra [ -f ]. Or après "-f" il faut impérativement quelque chose
    Solution: [ -f "$var" ]: ici plus de problème. Même si $var est vide, le shell verra [ -f "" ] et aura quelque chose à manipuler (ici une chaine vide mais ayant une existence)


    Citation Envoyé par Erlen Voir le message
    c'est quoi test une commande à écrire ou le -f entre les crochets.
    La commande qui sert à tester les choses se nomme "test" (tout comme celle qui sert à afficher les choses se nomme "echo"). La vraie syntaxe puriste est donc test -f fic. Les crochets ne sont qu'un alias de cette commande. C'est dommage qu'ils soient enseignés en premier dans la majorité des cours shells car on perd alors certains fondements qui empêchent de comprendre des syntaxes comme celles-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if ls
    ...
    while read
    ...
    until grep
    ...

  5. #5
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 587
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 587
    Points : 19 468
    Points
    19 468
    Par défaut
    J'utilise bash comme interpréteur. Je sais qu'il ne gère pas les tableaux
    SH n'a pas de tableaux.
    BASH, lui, peut utiliser des tableaux indexés, et il peut aussi utiliser des tableaux associatifs, qui sont non plus indexés numériquement, mais dont les index peuvent contenir du texte, depuis la version 4. Par contre, ces derniers doivent déclarés explicitement avec declare -A nom_TabloAssoc.

    SH != BASH
    SH, ou Bourne shell, n'implémente que la norme POSIX.
    BASH, ou Bourne Again SHell, implémente la norme POSIX, mais a ajouté quelques extensions ( certains remplacements de paramètres, les double-crochets, les tableaux (indexés et associatifs), etc.).

    Citation Envoyé par Sve@r
    La vraie syntaxe puriste est donc test -f fic. Les crochets ne sont qu'un alias de cette commande. C'est dommage qu'ils soient enseignés en premier dans la majorité des cours shells car on perd alors certains fondements qui empêchent de comprendre des syntaxes
    ouaip, +1.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 162
    Points : 66
    Points
    66
    Par défaut
    Merci pour toutes ses explications.
    Je modifierai mon script pour le test des variables,
    d'ailleurs, doit on écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if [ -f toto-"$d1"-"$d2".out* ]
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if [ -f "toto-$d1-$d2.out*" ]
    La première me semble juste.
    Mais au passage je vous fais remarquer que dans ce cas précis et j'insiste sur ce cas précis, $d1 et $d2 ne peuvent pas être vide puisqu'ils sont issus de $i et $j définis pas la boucle. Mais merci pour l'info.
    En ce qui concerne les tableaux je vais regarder ça de plus près, au passage vous n'auriez pas des sites qui expliquent un peu tout ça, un des problèmes sur internet c'est qu'on trouve plein de chose notamment de nombreuses bidouilles qui fonctionnent mais qui ne sont pas forcément un bon exemple au regard de ce que devrait être un code bien fait !

  7. #7
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 587
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 587
    Points : 19 468
    Points
    19 468
    Par défaut
    heu... ni l'une, ni l'autre
    la deuxième est mieux si tu enlèves l'astérisque.

    pour les tuto :
    il y a ceux inscrits dans ma signature
    The Linux Documentation Project (anglophone) en propose quelques uns :
    - bash beginners guide (quelque chose dans le genre)
    - advanced bash scripting
    ...
    et celui de Sve@r

    edit: encore un bon site (anglophone) :bash.hackers.org

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 721
    Points : 31 044
    Points
    31 044
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Erlen Voir le message
    Merci pour toutes ses explications.
    Je modifierai mon script pour le test des variables,
    d'ailleurs, doit on écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if [ -f toto-"$d1"-"$d2".out* ]
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if [ -f "toto-$d1-$d2.out*" ]
    La première me semble juste.
    Faut pas exagérer. Les guillemets sont là pour montrer l'existence au cas où il n'y aurait rien. Donc l'encapsulation unique de la seconde proposition suffit. Toutefois tu auras un problème avec l'étoile car quand elle est mise entre guillemets elle n'est plus interprétée.
    Donc théoriquement, la syntaxe exacte parfaite serait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if [ -f "toto-$d1-$d2.out"* ]
    Le problème, c'est que même là, le shell ne comprendra pas ce que tu veux faire car s'il y a 3 fichiers dont le nom commence pareil, le test sera interprété de cette façon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if [ -f "toto-$d1-$d2.out"v1 "toto-$d1-$d2.out"v2 "toto-$d1-$d2.out"v3 ]
    et tu retombes sur mon premier exemple...

    Citation Envoyé par Erlen Voir le message
    Mais au passage je vous fais remarquer que dans ce cas précis et j'insiste sur ce cas précis, $d1 et $d2 ne peuvent pas être vide puisqu'ils sont issus de $i et $j définis pas la boucle. Mais merci pour l'info.
    Il s'agit d'une règle de vie générale. Si tu prends l'habitude de les mettre tout le temps, tu n'auras aucun soucis même si la variable ne peut pas être vide. De plus ils servent aussi à protéger les espaces. C'est rare mais il peut arriver qu'un nom de fichier en contienne.
    Donc si tu as un fichier qui se nomme "mon fichier" tu es, là aussi, obligé de le mettre entre guillemets...



    Citation Envoyé par N_BaH Voir le message
    +1

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 162
    Points : 66
    Points
    66
    Par défaut
    Je comprends pas bien la différence entre votre tableau
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    declare -A nom_TabloAssoc
    et le mien.
    Dans les deux cas ce sont des tableaux ligne (ou colonne c'est selon la façon d'on on voit les choses).

  10. #10
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 587
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 587
    Points : 19 468
    Points
    19 468
    Par défaut
    dans un tableau indexé, déclaré ainsi : declare -a tableauIndexC, ou implictement tableauIndexC=( foo bar baz ), les index sont des nombres.

    dans un tableau associatif, déclaré ainsi : declare -A tableauAsso, et qui ne peut pas être déclaré implicitement, les index sont du texte.
    par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ declare -A peuImporte
    $ peuImporte=( [abc]="quoi que ce soit" [1_3]="comme dans ton tableau" )
    $ peuImporte["un autre"]="histoire de"
    $ printf '%s\n' "${peuImporte[@]}"
    comme dans ton tableau
    quoi que ce soit
    histoire de
    $ for item in "${!peuImporte[@]}"; do echo "$item = ${peuImporte[$item]}"; done
    1_3 = comme dans ton tableau
    abc = quoi que ce soit
    un autre = histoire de
    tu remarqueras que ni l'ordre d'entrée, ni l'ordre alphabétique ne sont respectés. C'est parce que ce type de tableau est hashé.

Discussions similaires

  1. [2008R2] SQLCMD faire une boucle sur une query
    Par janlouk dans le forum Développement
    Réponses: 2
    Dernier message: 25/06/2015, 14h10
  2. [XL-2010] Une boucle sur 500000 ligne lente
    Par moi244 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 27/12/2012, 23h19
  3. revenir sur une boucle sur homebrew psp
    Par tanguynoub dans le forum C
    Réponses: 15
    Dernier message: 27/05/2012, 16h10
  4. [XSLT] Faire une boucle sur une variable [i]
    Par PoT_de_NuTeLLa dans le forum XSL/XSLT/XPATH
    Réponses: 8
    Dernier message: 07/06/2010, 12h45
  5. une colle sur une boucle
    Par blastfr dans le forum SAS Base
    Réponses: 6
    Dernier message: 27/04/2010, 15h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo