Conserver le résultat d'une commande incrémentée dans autant...

Résolu/Fermé
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 - Modifié par Swiss Knight le 1/05/2013 à 13:07
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 - 11 mai 2013 à 13:09
Bonjour tout le monde,

Je cherche dans un script bash à conserver le résultat d'une commande incrémentée dans autant de variables.

Exemple :
n=3;                 
h=900;                 
w=1200;                
A="171 169 171 52 45 44 187 186 187 131 129 128 79 67 63 164 162 162 159 130 115 182 134 105 205 206 207"


Et dans une double boucle :
for j in 'seq 1 1 $[n]'; do                
        qcx[${j}]=$[(2*j-1)*w/(2*n)];                
        for k in 'seq 1 1 $[n]'; do                
            qcy[${k}]=$[(2*k-1)*h/(2*n)];                
            qc[${j}${k}]=${qcx[${j}]},${qcy[${k}]};                
            B[${j}${k}]= quelque chose                
        done                
    done


Et le quelque chose, ce serait les lignes du résultat de cette commande :
'echo ${A} | awk '{for (i=1; i+2<=NF; i+=3) {print $i, $(i+1), $(i+2)} }''


Chaque ligne doit être stockée comme un élément du tableau B, d'indice j,k.
Et chaque ligne comporte un triplet de nombres.

Pour expliquer plus en détails, j'ai un carré, divisé en n dimensions. Comme une grille de tic-tac-toe.
Et chaque case de ce carré doit être représentée par ses coordonnées (contenues dans A, mais toutes à la suite et sans pouvoir facilement y faire référence dans la suite du code) dans un espace à 3 dimensions.
La dimension de cet espace est 3, mais celles du carré peuvent être bien plus grandes que 3, et la variable A contiendra d'autant plus de valeurs (3*n^2 pour être précis). Dans l'exemple ci-dessus, la variable A contient 9 triplets de nombres. Si n valait 5, elle en contiendrait 15, etc.

Donc le but est de pouvoir "indexer" les coordonnées contenues dans A en les passants dans un tableau B indexé (donc d'indice j,k).

Je sais déjà que je vais rencontrer un problème avec "l'ordre" des cases... Mais j'ai choisi de les numéroter par cette double boucle; l'indice j représentant le numéro de la colonne, et k de la ligne.
Les cases sont classée dans le sens de la lecture : du haut à gauche jusqu'en bas à droite. Donc la case d'indice [jk]=[11] est la première, et B[11] doit être égal à 171 169 171
B[21]=52 45 44
B[31]=187 186 187
B[12]=131 129 128
B[22]=79 67 63
B[23]=164 162 162
B[31]=159 130 115
B[32]=182 134 105
et finalement B[33]=205 206 207

J'espère que tout est clair.

4 réponses

Utilisateur anonyme
1 mai 2013 à 13:00
#!/bin/bash

n=3
h=900 
w=1200
A="171 169 171 52 45 44 187 186 187 131 129 128 79 67 63 164 162 162 159 130 115 182 134 105 205 206 207"
a=( $A )
exec {foo}< <(for ((i=0;i<${#a[@]};i+=n)); do echo ${a[@]:$i:$n}; done)

for j in $(seq 1 $n)
do
   qcx[j]=$(( (2 * j-1) * w /(2*n) ))
   for k in $(seq 1 $n)
   do
      qcy[k]=$(( (2 * k-1) * h /(2*n) ))
      m=$j$k
      qc[m]="${qcx[j]},${qcy[k]}"
      read -u $foo qqch
      B[m]="$qqch"
   done
done
1
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
1 mai 2013 à 13:57
Salut,

for j in $(seq 1 $n)
Il m'avait cru comprendre qu' avec bash seq était inutile et qu'il valait mieux utiliser l'évaluation arithmétique... ;-\
0
oui, j'avais d'autres choses en vue.
mais, j'aurais dû corriger ça aussi ;)
0
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 110
1 mai 2013 à 13:19
Merci pour ta réponse qqchquicommenceparQ,

1. J'essaie de la décortiquer pour bien comprendre :

a=( $A ) transforme la variable A en un tableau a ?

exec {foo}< <(for ((i=0;i<${#a[@]};i+=n)); do echo ${a[@]:$i:$n}; done)
définit une fonction "foo" ?

read -u $foo qqch
B[m]="$qqch"
ça je ne comprends pas très bien ce que ça fait


______________________

2.

il y a un petit couac avec a=( $A ) : le tout premier nombre de la variable A est un zéro. Je ne le retrouve pas dans a. Ça commence directement à 255.

! Merci !
0
Utilisateur anonyme
1 mai 2013 à 13:31
foo est le numéro d'un descripteur de fichier (généré par bash, et supérieur à 10 par sécurité), c'est un "FIFO interne".

read -u lit une ligne de $foo en la consommant: elle disparaît du descripteur.

j'ai ajouté un 0 à A, et je n'ai pas de problème, il apparaît bien.
0
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 110
1 mai 2013 à 16:32
Très bien, merci. Ce sont des notions qui me dépassent légèrement, mais j'ai réussi grâce à vos précieux conseils.
Après avoir changé les seq, je n'ai plus eu de problème au niveau du premier zéro. Peut-être était-ce lié ? Peut-être que j'ai changé d'autres trucs entre deux, j'en sais plus trop rien à vrai dire mais ça joue maintenant.

Merci infiniment.
0
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 110
1 mai 2013 à 19:45
Re Bonjour,

Il y a un petit problème... ;) :
les dimensions de l'espaces sont confondues avec les dimensions de la grille !

Si n=2 je n'ai pas un triplet, mais un doublet de nombres dans B[jk], si n=5 j'en ai 5, etc.
Et pour n>3, une fois tous les nombres de A épuisés, il n'y a plus rien à stocker !
Or ce sont toujours des triplets qu'il faut conserver dans les cellules de B.

Exemple :

n=4
A="171 169 171 52 45 44 187 186 187 131 129 128 79 67 63 164 162 162 159 130 115 182 134 105 205 206 207 150 201 204 251 241 222 120 124 158"
h=900
w=1200

a=( $A )
exec {foo}< <(for ((i=0;i<${#a[@]};i+=3)); do echo ${a[@]:$i:$n}; done)

for j in $(seq 1 $n)
do
qcx[j]=$(( (2 * j-1) * w /(2*n) ))
for k in $(seq 1 $n)
do
qcy[k]=$(( (2 * k-1) * h /(2*n) ))
m=$j$k
qc[m]="${qcx[j]},${qcy[k]}"
read -u $foo qqch
B[m]="$qqch"
done
done


$ echo ${B[11]}
171 169 171 52

alors qu'il devrait toujours valoir 171 169 171.



>> je pense qu'il faut corriger la ligne :
exec {foo}< <(for ((i=0;i<${#a[@]};i+=n)); do echo ${a[@]:$i:$n}; done)
en
exec {foo}< <(for ((i=0;i<${#a[@]};i+=3)); do echo ${a[@]:$i:3}; done)

je vais tester ça...


0
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 110
1 mai 2013 à 21:56
ok ça a l'air de fonctionner en remplaçant cette ligne exec.
par contre je ne sais pas si elle a encore du sens ?! (i.e. si elle serait remplaçable par quelque chose de plus simple).
0
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 110
Modifié par Swiss Knight le 11/05/2013 à 12:26
Je signale juste un sérieux bug lorsque xx ou yy dépasse 9, l'indice du tableau part en sucette je crois... il ne sait plus faire la différence entre certaines cellules ; par exemple, 10;1 et 1;01, ou 11;2 et 1;12, etc.

J'essaye de trouver une alternative.

ce truc fonctionne bien :
https://www.commandlinefu.com/commands/view/7921/tricky-implementation-of-two-dimensional-array-in-bash.
    for xx in $(seq 1 ${n} ); do   
        qcx[${xx}*100]=$[(2*(xx)-1)*w/(2*n)];   
        for yy in $(seq 1 ${n} ); do   
            qcy[${yy}]=$[(2*(yy)-1)*h/(2*n)];   
            qc[${xx}*100+${yy}]=${qcx[${xx}*100]},${qcy[${yy}]};   
            read -u ${descripteur} table   
            A[${xx}*100+${yy}]="${table}"   
            B[${xx}*100+${yy}]='echo ${A[${xx}*100+${yy}]} | sed 's/\( \)/,/g''   
            myvar+='echo "${qc[${xx}*100+${yy}]}"' Aa('"${B[${xx}*100+${yy}]}"') ''   
        done   
    done


"Si vous ne pouvez expliquer un concept à un enfant de six ans, c'est que vous ne le comprenez pas complètement." -A. Einsten-
0
Utilisateur anonyme
11 mai 2013 à 12:51
Tu devrais sérieusement envisager d'utiliser un langage qui supporte réellement les tableaux multidimensionnels (tu te causeras moins d'ennuis).

Si tu persistes à vouloir utiliser un langage simple, alors tu devrais passer par un tableau associatif (en bash, ksh, ou awk) dont l'indice comportera un séparateur quelconque, ou prédéfini (pour awk), pour distinguer abscisses et ordonnées.
Je préférerais awk.

bien sûr, on peut aussi se servir d'un tournevis pour couper du papier.

Tu devrais sérieusement envisager d'utiliser un langage qui supporte réellement les tableaux multidimensionnels.
0
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 110
11 mai 2013 à 13:09
Ouais je sais pas, je ne connais pas spécialement de langages.
Et je ne connais pas les tableaux associatifs (vais me renseigner sur la question).

Sais-tu pourquoi le bash ne permet pas de traiter des tableaux de plus d'une dimension (déjà 2 ce serait sympa je me dis) ?

:-)
0