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 :

[Bash] Variable "dynamique"


Sujet :

Shell et commandes GNU

  1. #1
    Invité
    Invité(e)
    Par défaut [Bash] Variable "dynamique"
    Bonjour à tous,
    J'ai passé plusieurs heures sur ce problème sans succès.
    Je vous explique:

    A la racine j'ai un fichier main qui va appeler une fonction verification (cette fonction est à l'emplacement /FR/verif.sh)
    Au même emplacement (mais dans un fichier différent) j'ai un fichier où sont déclarés des serveurs de la façon suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    declare -a srv-messagerie=( mess1 mess2  ... )
    declare -a srv-DNS=( dns1 dns2 ... )
    ........

    Dans le main j'appelle ma fonction avec un paramètre donné par un for qui parcourt un tableau représentant le type de serveur (messagerie, dns, etc....

    Quand j'arrive dans ma fonction avec le paramètre "messagerie", j'aimerais parcourir tous les serveurs présents dans srv-messagerie.
    Pour ce faire je fais une boucle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    type=$1
    for i in ${srv-${type}[@]}
    Le problème c'est que ça ne marche pas. J'obtiens bad substitution.

    Par contre si je mets "en dur" srv-messagerie[@] là ça fonctionne.

    Avez-vous une idée comment régler le problème?

    Je vous remercie.

    Bon week-end
    Dernière modification par N_BaH ; 26/05/2021 à 21h34.

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    Bonjour

    Tu cherches à faire un tableau à 2 dimensions. Mais en shell, on a souvent recours à un fichier en guise de tableau à 2 dimensions. Ne serait-il pas plus propre d'avoir ce fichier :
    messagerie mess1
    messagerie mess2
    DNS dns1
    DNS dns2
    
    que tu traiterais par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while read type_server address_server other
    do
        # traitement en fonction du type $type_server. avec des ifs ou des cases
    done < mon_fichier_de_serveurs.txt
    ?
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  3. #3
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    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 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Ou une methode très spécifique bash:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ## partie code inutile, juste pour la demo
    $ set messagerie
    $ echo $1
    messagerie
    ## fin de code inutile
    $ declare -a srvmessagerie=(mess1 mess2)
    $ declare -n s_type=srv$1
    $ echo ${s_type[@]}
    mess1 mess2
    Cordialement.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 550
    Points : 19 383
    Points
    19 383
    Par défaut
    on peut créer des pseudo-tableaux pseudo-multidimensionnels :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    declare -A srv
    sep=','
    srv=( 
       [$type$sep$nb]="serveurTypeN+1"
    ...
    )
    $sep un séparateur "constant" qui sera utilisé à la (re)lecture de l'indice.

    /!\ttention! srv est un tableau (associatif), mais srv[type,nb] est un élément (pas un tableau)
    si cet élément contient une liste, il faut construire cette liste avec un séparateur non-équivoque.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Bonsoir à tous,

    Je vous remercie grandement pour votre mobilisation.
    A première vue la solution de @disedorgue serait la plus adaptée à ma problématique.
    Je testerai dans les prochains jours et je reviendrai vers vous pour vous dire si le problème est résolu (mais je suis confiant).

    Bonne soirée et bon week-end à tous.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Bonjour à tous,
    @disedorgue j'ai testé votre solution mais ça ne marche pas dans mon code.

    La concaténation se fait bien: srv- + valeur du paramètre

    Mais quand je fais un echo de ma variable il imprime: srv-messagerie mais il ne me donne pas ce qui est contenu dans srv-messagerie i.e mess1 mess2

    Dans l'exemple que vous avez mis, vous faite: declare -n
    On est d'accord que c'est declare -a ?

    Il faut savoir que mes serveurs sont déclarés dans un fichier serveurs.
    Alors que tout le travail (concaténation, boucle sur les valeurs contenues dans srv-messagerie) se fait dans un autre fichier (au même emplacement) via une fonction.

    Il n'y a pas besoin d'importer quoi que se soit étant donné que les 2 fichiers sont dans le même répertoire?

    Je vous remercie.

    Bonne soirée

  7. #7
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    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 278
    Points : 12 726
    Points
    12 726
    Par défaut
    non, c'est bien declare -n et comme j'ai dis, c'est du pur bash (pas un autre shell).

    Essaye l'exemple que j'ai donné, celui-ci est fonctionnel, faut juste le comprendre.

    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    $ help declare
    declare: declare [-aAfFgilnrtux] [-p] [nom[=valeur] ...]
        Définit les valeurs et les attributs des variables.
        
        Déclare des variables et leur assigne des attributs.  Si aucun NOM n'est donné,
        affiche les attributs et les valeurs de toutes les variables.
        
        Options :
          -f	restreint l'action ou l'affichage aux noms et définitions de fonctions
          -F	restreint l'affichage aux noms des fonctions uniquement (avec le numéro de ligne
        		et le fichier source lors du débogage)
          -g	crée des variables globales lorsqu'utilisée dans une fonction shell ; ignoré sinon
          -p	affiche les attributs et la valeur de chaque NOM
        
        Options qui définissent des attributs :
          -a	pour faire de NOMs des tableaux indexés (si pris en charge)
          -A	pour faire de NOMs des tableaux associatifs (si pris en charge)
          -i	pour assigner l'attribut « integer » aux NOMs
          -l	pour convertir la valeur de chaque NOM en minuscules lors de l'affectation
          -n	transforme NOM en une référence vers une variable nommée d'après sa valeur
          -r	pour mettre les NOMs en lecture seule
          -t	pour permettre aux NOMs d'avoir l'attribut « trace »
          -u	pour convertir les NOMs en majuscules lors de l'affectation
          -x	pour permettre aux NOMs de s'exporter
        
        Utiliser « + » au lieu de « - » pour désactiver l'attribut.
        
        Les variables avec l'attribut « integer » ont une évaluation arithmétique (voir
        la commande « let ») effectuée lorsqu'une valeur est affectée à la variable.
        
        Lorsqu'utilisée dans une fonction, « declare » permet aux NOMs d'être locaux,
        comme avec la commande « local ». L'option « -g » supprime ce comportement.
        
        Code de retour :
        Renvoie le code de succès à moins qu'une option non valable soit fournie ou qu'une
        erreur survienne lors de l'assignation d'une variable.
    Cordialement.

  8. #8
    Invité
    Invité(e)
    Par défaut
    J'ai bien compris ton exemple.

    J'appelle mon script via: bash xxxxx.sh

    Je pense donc que ta solution n'est donc pas applicable à mon exemple car je ne dois pas être sur dû pur Bash.

    Y-a-t-il une équivalence à ta solution?

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 550
    Points : 19 383
    Points
    19 383
    Par défaut
    si tu appelles bash* avec ton script (peu importe l'extension**) en tant qu'argument, alors c'est bash qui exécutera le script !

    --
    * ou si le le script est exécutable, et que son shebang est bash
    ** les extensions sur linux ne sont qu'indicatives; elles n'induisent aucunes obligations contrairement à W$.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  10. #10
    Invité
    Invité(e)
    Par défaut
    c'est ce que je pensais mais lorsque que j'appelle mon script avec dans le code declare -n il me dit que -n n'est pas option

    Je ne comprends pas alors

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 550
    Points : 19 383
    Points
    19 383
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bash --version | head -1
    ? stp.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  12. #12
    Invité
    Invité(e)
    Par défaut
    Le retour de la commande est:

    GNU bash, version 4.2.46(2)-release (x86_64redhat-linux)

    Quand je fais: help declare

    Je n'ai pas l'option n
    Dernière modification par Invité ; 26/05/2021 à 09h20.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 550
    Points : 19 383
    Points
    19 383
    Par défaut
    tu as ton explication : version trop ancienne, qui ne dispose pas de cette option.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  14. #14
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    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 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Et oui, reste plus qu'à passer par un eval...

    Soit dit en passant, je comprend mieux pourquoi mon bash n'accepte pas des non de variable tel que srv-messagerie.
    Cordialement.

  15. #15
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 101
    Points : 5 849
    Points
    5 849
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Soit dit en passant, je comprends mieux pourquoi mon bash n'accepte pas des noms de variable tels que srv-messagerie.
    Moi aussi !
    Merci !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ a-b=c
    -bash: a-b=c: command not found
     
    $ a_b=c
     
    $ bash --version | head -1
    GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 550
    Points : 19 383
    Points
    19 383
    Par défaut
    bash 3

    c'était une évolution il y a combien de temps ?
    à moment, quand même, il faut mettre à jour !
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 550
    Points : 19 383
    Points
    19 383
    Par défaut eval, c'est mal. eval, c'est mal. eval, c'est mal. eval, c'est mal. eval, c'est mal. eval, c'est mal. eval, c'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ srv_msg=( "msg 1" "msg 2" ) # `srv_' parce que même avec bash5, `-' est un caractère illégal dans un nom de variable.
    $ srv_dns=( "dns 1" "dns 2" )
    $ for a in ${!srv_*}; do echo "$a :"; ar="${a}[@]"; printf '    %s\n' "${!ar}"; done
    srv_dns :
        dns 1
        dns 2
    srv_msg :
        msg 1
        msg 2
    $
    merci qui ?
    merci Greg !
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  18. #18
    Invité
    Invité(e)
    Par défaut
    Bonsoir,
    Merci à tous.
    J'aurais appris l’existence et l'utilité de l'option -n avec un bash récent.

    Juste pour ma culture de débutant pourquoi le eval est mal?

    Bonne soirée

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 550
    Points : 19 383
    Points
    19 383
    Par défaut
    parce que ça interprète tout comme une commande, et donc, quand on ne maîtrise pas ce qui entre dans le script, c'est extrêmement périlleux.
    enfin, si tout est contrôlé, ce n'est pas plus dangereux qu'une substitution de commande.

    en ce qui me concerne, c'est un dogme, et dès que j'en arrive à me dire que je vais devoir m'en servir, je cherche une autre solution, voire, je revois totalement mon algorithme : autre départ -> autre arrivée !
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  20. #20
    Invité
    Invité(e)
    Par défaut
    D'accord je vois

    Je vous remercie pour toutes ces explications et pour l'aide que vous m'avez tous apporté.

    J'ai la sensation d'avoir appris pleins de choses avec cette discussion.

    Bonne soirée à tous

Discussions similaires

  1. variable dynamique dans une fonction javascript
    Par Shivaneth dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 20/04/2005, 15h58
  2. Variables dynamiques
    Par CriPpLe dans le forum C++
    Réponses: 5
    Dernier message: 23/02/2005, 11h56
  3. [SQL SERVER 2000] Noms de variables dynamiques
    Par cassoulet dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 08/09/2004, 11h44
  4. Récupération de variables dynamiques complexes
    Par ludoboy dans le forum ASP
    Réponses: 7
    Dernier message: 24/05/2004, 17h51
  5. [LG]Problême Variable dynamique de types différents
    Par pierrOPSG dans le forum Langage
    Réponses: 2
    Dernier message: 29/04/2004, 16h01

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