96 votes

Comment déclarer un tableau 2D en bash

Je me demande comment déclarer un tableau 2D en bash et l'initialiser à 0.

En C, cela ressemble à ceci :

int a[4][5] = {0};

Et comment attribuer une valeur à un élément ? Comme en C :

a[2][3] = 3;

3 votes

4 votes

En fait, un tableau multidimensionnel est en réalité (au fond) un tableau unidimensionnel, qui est géré un peu différemment, notamment lorsqu'il s'agit d'accéder à ses éléments. Par exemple, une matrice 3x4 comporte 12 cellules. Les "lignes" sont parcourues avec une boucle externe avec un pas de 3 et les "colonnes" sont parcourues avec une boucle interne avec un pas de 1.

89voto

jm666 Points 17312

On peut les simuler par exemple avec des hachages, mais il faut alors se préoccuper des zéros de tête et de bien d'autres choses. La démonstration suivante fonctionne, mais elle est loin d'être une solution optimale.

#!/bin/bash
declare -A matrix
num_rows=4
num_columns=5

for ((i=1;i<=num_rows;i++)) do
    for ((j=1;j<=num_columns;j++)) do
        matrix[$i,$j]=$RANDOM
    done
done

f1="%$((${#num_rows}+1))s"
f2=" %9s"

printf "$f1" ''
for ((i=1;i<=num_rows;i++)) do
    printf "$f2" $i
done
echo

for ((j=1;j<=num_columns;j++)) do
    printf "$f1" $j
    for ((i=1;i<=num_rows;i++)) do
        printf "$f2" ${matrix[$i,$j]}
    done
    echo
done

l'exemple ci-dessus crée une matrice 4x5 avec des nombres aléatoires et l'imprime transposée, avec le résultat de l'exemple

           1         2         3         4
 1     18006     31193     16110     23297
 2     26229     19869      1140     19837
 3      8192      2181     25512      2318
 4      3269     25516     18701      7977
 5     31775     17358      4468     30345

Le principe est le suivant : Créer un tableau associatif où l'index est une chaîne de caractères comme 3,4 . Les avantages :

  • il est possible de l'utiliser pour des tableaux de n'importe quelle dimension ;) comme : 30,40,2 pour 3 dimensions.
  • la syntaxe est proche de celle du "C", comme les tableaux. ${matrix[2,3]}

3 votes

L'inconvénient évident de cette méthode est que la longueur d'une dimension ne peut être connue. Néanmoins, elle fonctionne parfaitement dans la plupart des autres scénarios ! Merci !

0 votes

Pouvez-vous expliquer ce que f1 et f2 faire ?

1 votes

@Jodes le f1 et f2 contient le format pour le printf pour une impression bien alignée. Il pourrait être codé en dur, par exemple printf "%2s" mais l'utilisation de variables est plus flexible - comme dans l'exemple ci-dessus f1 . Le site width de la numéro de rang est calculé comme la longueur de $num_rows variable - par exemple, si le nombre de rangées $num_rows est 9, sa longueur est 1 le format sera 1+1 donc %2s . Pour le $num_rows 2500, sa longueur est 4 Le format sera donc %5s - et ainsi de suite...

24voto

Sir Athos Points 1936

Bash ne prend pas en charge les tableaux multidimensionnels.

Vous pouvez cependant la simuler en utilisant l'expansion indirecte :

#!/bin/bash
declare -a a0=(1 2 3 4)
declare -a a1=(5 6 7 8)
var="a1[1]"
echo ${!var}  # outputs 6

Les affectations sont également possibles avec cette méthode :

let $var=55
echo ${a1[1]}  # outputs 55

Edit 1 : Pour lire un tel tableau à partir d'un fichier, avec chaque ligne sur une ligne, et les valeurs délimitées par des espaces, utilisez ceci :

idx=0
while read -a a$idx; do
    let idx++;
done </tmp/some_file

Edit 2 : Déclarer et initialiser a0..a3[0..4] à 0 tu pourrais courir :

for i in {0..3}; do
    eval "declare -a a$i=( $(for j in {0..4}; do echo 0; done) )"
done

0 votes

Pouvez-vous me montrer comment remplir la "simulation de tableau 2d" ci-dessus à partir d'un fichier-tableau ? Par exemple, j'ai un fichier avec un nombre aléatoire de lignes et dans chaque ligne, 5 nombres délimités par des espaces.

0 votes

@kobame : J'ai édité la réponse pour fournir une solution à ce que vous demandez. Il lira un tableau 2d avec un nombre variable de lignes et un nombre variable de colonnes, en a0, a1 et ainsi de suite.

0 votes

Comment utiliseriez-vous un autre délimiteur tel qu'une virgule ou une tabulation ?

5voto

James Andino Points 3272

Vous pouvez également aborder cette question de manière beaucoup moins intelligente.

q=()
q+=( 1-2 )
q+=( a-b )

for set in ${q[@]};
do
echo ${set%%-*}
echo ${set##*-}
done

bien sûr, une solution à 22 lignes ou une indirection est probablement la meilleure façon de procéder et pourquoi ne pas saupoudrer de l'évaluation un peu partout ?

0 votes

Où la solution de 22 lignes utilise-t-elle l'indirection ? Pour votre solution, qu'allez-vous faire lorsque vous écrivez un script qui nécessite des entrées/sorties et qu'un utilisateur veut entrer un - dans le "tableau". De même, si vous souhaitez simuler un tableau, il est probablement plus judicieux d'utiliser la méthode suivante echo ${set//-/ } au lieu de vos deux.

0 votes

Je pense que ${set//-/} est probablement une meilleure solution (je ne connais pas les problèmes de portabilité de %% et ##, mais je vous crois). La question "Et si" est très dangereuse, si vous la posez trop souvent, vous vous rendrez compte que vous avez besoin d'une I.A. pour votre analyseur d'options :{p

1 votes

Je ne comprends pas en quoi cela est pertinent ou aide à répondre à la question. ${set//-/ } éliminerait le '-', en fusionnant les valeurs. Par exemple, l'écho renvoie 'ab' alors que le code original renvoie soit 'a' soit 'b' selon le côté du '-' que vous voulez.

2voto

Atle Points 742

Comme l'a dit @Alper, Bash ne dispose pas de tableaux multidimensionnels. Vous devez le simuler. Cette page contient un exemple au bas de la page : http://tldp.org/LDP/abs/html/arrays.html

1voto

abasu Points 1564

Bash ne supporte pas les tableaux à 2 dimensions, mais il existe des passerelles en fonction de ce que vous voulez. Comme awk fonctionne en bash et supporte les tableaux 2d. http://www.gnu.org/software/gawk/manual/html_node/Multi_002ddimensional.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X