Forum Programmation.shell Utiliser une concaténation de variable dans FOR

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
1
13
juil.
2015

Bonjour,

Pour réduire un code (qui est plus long que l'exemple), et pour ne pas mourir idiot, j'aurais besoin de savoir comment transformer ceci:

Lib1=0
Sat1=0
Lib2=0
Sat2=0
Lib3=0
Sat3=0
Lib4=0
Sat4=0
Lib5=0
Sat5=0
Lib6=0
Sat6=0
Lib7=0
Sat7=0

en ceci, mais ça ne fonctionne pas, mais dans l'idée, je ne dois pas être bien loin:

for x in Lib Sat
do for y in `seq 7`
$x$y=0
done
done

Curieusement si je fais un simple:
echo $x$y
ça me donne bien ce que je souhaites …

Si quelqu'un passe dans le coin et peux m'expliquer comment faire svp
j'ai cherché un peu partout, essayé pleins de trucs, je bloque !

HELP

Ah et désolé je n'arrive pas à placer les balises codes depuis mon poste de travail .

  • # pas très clair mais ...

    Posté par  . Évalué à 3.

    … mais i j'ai bien compris, man eval (tu ne m'en voudras pas d'être aussi flou que ton énoncé :)

  • # eval

    Posté par  . Évalué à 4.

    Tu peux utiliser la commande eval pour fabriquer une commande shell à partir de texte.

    Par exemple :

    $ unset Sat1
    $ x=Sat
    $ y=1
    $ $x$y=0  # incorrect
    bash: Sat1=0: command not found
    $ eval $x$y=0 # ça marche
    $ echo $Sat1
    0
    
  • # eval

    Posté par  (site web personnel) . Évalué à 2.

    Il faut faire un eval si tu veux paramétrer le nom de tes variables comme tu le fait.

  • # Autres pistes

    Posté par  (site web personnel) . Évalué à 5.

    Plusieurs ont indiqué eval comme dans

    for x in Lib Sat
    do for y in seq 7
      eval ${x}${y}=0
    done
    done
    

    ce qui est une bonne piste de départ. Défaut important, c'est très lent, et quand je dis lent, c'est que pour peu que ta boucle soit un peu longuette, c'est lent de façon très visible. Voici donc quelques pistes pour tâcher de gagner en vitesse.

    Tu peux par exemple grouper les affectations, en faisant par exemple:

    prepare_init()
    {
      local x y
      for x in Lib Sat
      do for y in seq 7
        printf '%s%s=0\n' "${x}" "${y}"
        done
      done
    }
    
    eval $(prepare_init)
    

    Oui bien

    prepare_init()
    {
      local x y
      for x in Lib Sat
      do for y in seq 7
        printf '%s%s=0\n' "${x}" "${y}"
        done
      done
    }
    
    perform_init()
    {
       local external
       external=$(mktemp perform_init.XXXXXX)
       prepare_init > "${external}"
       . "${external}"
       rm "${external}"
    }
    
    perform_init
    

    Je ne sais pas ce que tu fais exactement, mais en général faire ce genre de choses en shell signale qu'on se trompe un peu de langage. Le shell sert à lancer des programmes, déplacer des fichiers, etc. et traiter les données c'est le travail des programmes, pas du shell qui sert essentiellement à créer la glue entre ces programmes. (C'est mon avis et je le partage — tout le monde n'est pas d'accord.)

  • # MERCI !!!

    Posté par  . Évalué à 2.

    Salut,

    merci à tous pour vos réponses instructives ^

    Déjà, désolé du retard de ma réponse, je n'ai pas accès au forum depuis mon poste de travail …

    Alors, pour répondre, ce que je fais c'est de lancer un script dans un putty, récupérer le LOG de putty, ensuite je fais un copier/coller dans excel et ça me donne un beau graphique !!
    C'est le moyen le plus simple que j'ai trouvé, vu que c'est assez compliqué pour récupérer les ficher sur le serveur duquel je lance le script ( le réseau de l'entreprise est verrouillé au possible )

    Donc, j'ai testé plusieurs façons, j'ai retenu la moins rapide, mais qui me suffit amplement, j'ai un sleep de 300s, donc bon … ce qui donne:

    for x in Lib Sat
      do for y in `seq 7`
         do eval $x$y=0
         done
       done
    

    J'ai tenté de faire la même chose pour un autre bout de code, encore plus répétitif, je n'y suis pas arrivé avec eval ni autre chose.
    Bon OK je n'arrive pas à grand chose ;)
    Mes premiers pas en shell, je suis plutôt batch normalement, personne n'est parfait ^

    Comme ma demande précédente, c'est pour raccourcir le script, là je sèche encore plus:

    # je souhaites réduire ça:

    for a in trkstat $Fsx1 | grep 'F '
    do for b in echo $a | grep 'F'
    do Lib1=$(($Lib1 + 1))
    done
    done
    Sat1=$(($Max1 - $Lib1))

    for c in trkstat $Fsx2 | grep 'F '
    do for d in echo $c | grep 'F'
    do Lib2=$(($Lib2 + 1))
    done
    done
    Sat2=$(($Max2 - $Lib2))

    for e in trkstat $Fsx3 | grep 'F '
    do for f in echo $e | grep 'F'
    do Lib3=$(($Lib3 + 1))
    done
    done
    Sat3=$(($Max3 - $Lib3))

    # en quelque chose comme ça, qui fonctionne …

    for z in seq 3
    do for a in trkstat $Fsx$z | grep 'F '
    do for b in echo $a | grep 'F'
    do Lib$z=$(($Lib$z + 1))
    done
    done
    Sat$z=$(($Max$z - $Lib$z))
    done

    Ah et je n'ai toujours pas compris pour les balises ;)

    Merci de votre aide et du temps que vous passez, et pas d'inquiétude si je met un peu de temps à répondre !

    • [^] # Re: MERCI !!!

      Posté par  . Évalué à 2.

      ne sachant pas ce que fait trkstat, je suis peut-être à côté de la plaque, mais s'il s'agit de compter des occurrences dans un flux, l'option -c de grep peut peut-être t'aider ?

      sinon, en modification mineure, tu peux remplacer la logique (Satn = 0; … Libn = Libn +1 …: Satn = Maxn - Libn) par (Satn = Maxn; … Satn = Satn - 1). C'est pas grand chose, mais ça réduit la quantité de code, donc améliore sa lisibilité.

      • [^] # Re: MERCI !!!

        Posté par  . Évalué à 2.

        C'est pas grand chose, mais ça réduit la quantité de code, donc améliore sa lisibilité.

        en y repensant, l'implication est excessive. Une réduction de la quantité de code n'implique pas toujours une meilleure lisibilité, mais là, oui :)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.