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 :

Modification d'une variable dans une boucle for


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti Avatar de CaptainKrabs
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 25
    Par défaut Modification d'une variable dans une boucle for
    Bonjour,

    je suis en train d'écrire un script pour soumettre des jobs sur cluster, seulement je rencontre une difficulté lorsque je dois modifier successivementdes variables à l'intérieur d'une boucle for. Je suis parvenu à isoler le problème dans le but de code suivant :

    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    #!/bin/bash
     
    echo un test rapide
     
    i=03
     
    declare "Lidar_Clouds_NO_rd""$i"=5863766
    echo Lidar_Clouds_NO_rd$i=$((Lidar_Clouds_NO_rd$i))
     
    declare "Lidar_Clouds_HSRL_rd""$i"=5863767
    echo Lidar_Clouds_HSRL_rd$i=$((Lidar_Clouds_HSRL_rd$i))
     
    i=04
     
    declare "Lidar_Clouds_NO_rd""$i"=5863768
    echo Lidar_Clouds_NO_rd$i=$((Lidar_Clouds_NO_rd$i))
     
    declare "Lidar_Clouds_HSRL_rd""$i"=5863769
    echo Lidar_Clouds_HSRL_rd$i=$((Lidar_Clouds_HSRL_rd$i))
     
    for i in `seq -w 03 04`
    do
            declare ""dependency_list_Merge_Clouds_rd"$i"=$((Lidar_Clouds_NO_rd$i))":"$((Lidar_Clouds_HSRL_rd$i))
            echo dependency_list_Merge_Clouds_rd$i=$((dependency_list_Merge_Clouds_rd$i))
    done
    Voici ce que j'obtiens à l'exécution :

    un test rapide
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Lidar_Clouds_NO_rd03=5863766
    Lidar_Clouds_HSRL_rd03=5863767
    Lidar_Clouds_NO_rd04=5863768
    Lidar_Clouds_HSRL_rd04=5863769
    ./rdiffm2_17_11.sh: ligne 24: 5863766:5863767 : erreur de syntaxe dans l'expression (le symbole erroné est «*:5863767*»)
    alors qu'à la dernière ligne, le résultat que j'aurais aimé obtenir est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dependency_list_Merge_Clouds_rd03=5863766:5863767
    dependency_list_Merge_Clouds_rd04=5863768:58637679
    Je ne comprends pas bien l'origine du problème. Selon moi, l'opération a effectué serait une concaténation, j'ai bien essayé différentes syntaxes comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     declare ""dependency_list_Merge_Clouds_rd"$i"="$((Lidar_Clouds_NO_rd$i))":"$((Lidar_Clouds_HSRL_rd$i))"
    mais je ne parviens pas à corriger l'erreur....

    Je vous remercie par avance de votre aide, si vous pouviez m'expliquer l'origine de mon erreur ?

  2. #2
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 287
    Par défaut
    Bonjour

    Réactions à chaud :
    • Sais-tu que commencer un nombre par un 0 le définit en octal (base 8). Est-ce vraiment ce que tu voulais faire ?
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      $ i=013
      $ echo $i
      013
      $ echo $((i))
      11
      Dans ton exemple, il n'y a qu'un chiffre, inférieur à 8. Donc bon. C'est invisible, mais dangereux.
    • $(( )) est l'évaluation arithmétique. Tu veux vraiment faire une évaluation arithmétique ? Que cela t'apporte ?
    • Tu te trompes sur la façon d'accéder à une variable.
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      $ for i in 3 4;do declare "toto_$i"=$((i+5))"texte en plus";done
      $ echo $toto_3
      8texte en plus
      $ echo $toto_4
      9texte en plus

  3. #3
    Membre averti Avatar de CaptainKrabs
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 25
    Par défaut
    Bonjour et merci pour ce début d'aide !

    1er point : Effectivement une fois j'avais déjà rencontré ce problème ... mais j'ai oublié ! Du coup c'est corrigé.

    2ème point : En fait je crois ne pas bien comprendre...car si j'essaie sans évaluation arithmétique alors je n'arrive pas à faire afficher ma variable correctement, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    declare "Lidar_Clouds_NO_rd$i"=5863766
    echo Lidar_Clouds_NO_rd$i=$Lidar_Clouds_NO_rd$i
    et j'obtiens alors :
    Comment alors faire afficher la valeur : 5863766 ?

    3eme point : en tenant compte de tes remarques, voici le nouveau code que je proposerais :
    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
    18
    19
    20
    21
    22
    23
    24
    25
    #!/bin/bash
     
    echo un test rapide
     
    i=3
     
    declare "Lidar_Clouds_NO_rd$i"=5863766
    echo Lidar_Clouds_NO_rd$i=$Lidar_Clouds_NO_rd$i
     
    declare "Lidar_Clouds_HSRL_rd$i"=5863767
    echo Lidar_Clouds_HSRL_rd$i=$((Lidar_Clouds_HSRL_rd$i))
     
    i=4
     
    declare "Lidar_Clouds_NO_rd$i"=5863768
    echo Lidar_Clouds_NO_rd$i=$((Lidar_Clouds_NO_rd$i))
     
    declare "Lidar_Clouds_HSRL_rd$i"=5863769
    echo Lidar_Clouds_HSRL_rd$i=$((Lidar_Clouds_HSRL_rd$i))
     
    for i in `seq -w 3 4`
    do
            declare "dependency_list_Merge_Clouds_rd$i"=$((Lidar_Clouds_NO_rd$i))":"$((Lidar_Clouds_HSRL_rd$i))
            echo dependency_list_Merge_Clouds_rd$i=$((dependency_list_Merge_Clouds_rd$i))
    done
    bien que l'erreur soit encore là ...

  4. #4
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 287
    Par défaut
    Plusieurs remarques :
    • Laisse tomber seq
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      for ((i=3;i<=4;i++))
      do 
          printf "%02i\n" $i
      done
    • Ce que tu cherches à faire est une indirection.
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      $ for i in 3 4;do declare "toto_$i"=$((i+5))"texte en plus";n="toto_$i";echo "toto_$i=${!n}"; done
      toto_3=8texte en plus
      toto_4=9texte en plus
    • Mais en fait, je déconseille de prendre cette voie-là. Tu fais un tableau sans le dire. Et c'est compliqué pour rien.
      Si tu veux une variable, fais une variable.
      Si tu veux un tableau à une dimension, fais un tableau à une dimension.
      Si tu veux des tableaux à 2 dimensions ou plus, ça n'existe pas. Généralement, on utilise un fichier. Et de manière général, le script shell prend des valeurs dans des fichiers et les envoie dans des fichiers.
      Je ressens dans ta méthode l'habitude de la programmation objet de tout mettre dans une variable (qui n'est jamais qu'un pointeur).
      Tu vas t'arracher les cheveux à faire ce bricolage, en shell. Définis tes vraies entrées, tes vraies sorties et fais autrement.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 651
    Par défaut
    Bonjour,

    la variable en echo dans la boucle n'est pas un nombre, elle n'a pas à être dans une Évaluation arithmétique ($((...))).
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  6. #6
    Membre averti Avatar de CaptainKrabs
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 25
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    Bonjour,

    la variable en echo dans la boucle n'est pas un nombre, elle n'a pas à être dans une Évaluation arithmétique ($((...))).
    Bonjour,

    D'accord merci , mais dans ce cas quelle serait la syntaxe qui permettrait de faire afficher correctement cette variable ?

    Je proposerais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo dependency_list_Merge_Clouds_rd$i=$(dependency_list_Merge_Clouds_rd$i)
    mais alors j'obtiens l'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ./rdiffm2_17_11.sh: ligne 24: dependency_list_Merge_Clouds_rd3 : commande introuvable
    dependency_list_Merge_Clouds_rd3=
    ./rdiffm2_17_11.sh: ligne 24: dependency_list_Merge_Clouds_rd4 : commande introuvable
    dependency_list_Merge_Clouds_rd4=

  7. #7
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 347
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 347
    Par défaut
    En bash les tableaux existent et tu y gagnerais à les utiliser car c'est beaucoup plus simple à maitriser et plus lisible que d'essayer à faire des pirouettes avec des variables aux noms variabilisés.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 651
    Par défaut
    D'accord merci , mais dans ce cas quelle serait la syntaxe qui permettrait de faire afficher correctement cette variable ?
    une indirection :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    declare dependency_list_Merge_Clouds_rd$i="$((Lidar_Clouds_NO_rd$i)):$((Lidar_Clouds_HSRL_rd$i))"
    v="dependency_list_Merge_Clouds_rd$i"
    echo "dependency_list_Merge_Clouds_rd$i=${!v}"
    les constructions de variables avec des noms incluant d'autres variables sont sources de complications, qui vont, à plus ou moins long terme, insurmontables.
    on obtient des résultats équivalents sans outre complication en utilisant un tableau (indexé, ou/et associatif).

    PS: attention aux guillemets inutiles.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  9. #9
    Membre averti Avatar de CaptainKrabs
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 25
    Par défaut
    D'accord merci à tous pour votre aide.

    Conclusion :
    -je fais attention aux nombres en octal
    -j'ai bien enlevé le "seq" de ma boucle for
    -j'ai supprimé les guillemets inutiles

    J'ai réussi à dépanner mon code en utilisant une indirection, mais effectivement il va falloir que j'apprenne à utiliser les tableaux pour faire ça proprement !

    Merci encore de votre aide

Discussions similaires

  1. Réponses: 3
    Dernier message: 17/04/2014, 10h26
  2. [Batch] Déclaration variable dans un boucle FOR
    Par mouelhi0712 dans le forum Scripts/Batch
    Réponses: 1
    Dernier message: 02/09/2012, 20h33
  3. Réponses: 4
    Dernier message: 28/01/2010, 16h38
  4. Creer des variables dans un boucle for
    Par zentro dans le forum Général Python
    Réponses: 2
    Dernier message: 06/04/2008, 07h22
  5. [VB.net] Declaration variable dans une boucle for
    Par nico10gbb dans le forum Windows Forms
    Réponses: 4
    Dernier message: 10/05/2006, 11h45

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