bash array avec une variable dans le nom

J'apprécierai votre aide avec le problème suivant:

J'essaie de définir un tableau qui contient une variable faisant partie du nom du tableau, par exemple: Arr_$COUNTER (où $COUNTER est modifié en fonction du nombre de loops)

Chaque fois que j'ai essayé, j'ai trouvé une erreur, comme "mauvaise substitution" ou "erreur de syntaxe près d'un jeton inattendu"

Voici tout le stream:

  1. Il y a un file qui contient plusieurs lignes. chaque ligne a 6 valeurs séparées par l'espace

     10 20 30 40 50 60 100 200 300 400 500 600 
  2. Le script, est destiné à lire chaque ligne à partir du file, et le déclare comme un tableau (avec le numéro de ligne qui est la variable.

  3. comme test, chaque valeur doit être imprimée et éventuellement une autre fonction sera exécutée sur chaque valeur.

     #!/bin/bash COUNTER=1 LINES=`wc -l VALUES_FILE.txt | awk '{print $1}'` echo "Total number of lines "$LINES echo while [ $COUNTER -le $LINES ] do echo "Counter value is $COUNTER" field=`awk "NR == $COUNTER" VALUES_FILE.txt` echo "Field = $field" declare -a "arr$COUNTER=($field)" echo "arr$COUNTER[0] = ${arr$COUNTER[0]}" echo "arr$COUNTER[1] = ${arr$COUNTER[1]}" echo "arr$COUNTER[2] = ${arr$COUNTER[2]}" echo "arr$COUNTER[3] = ${arr$COUNTER[3]}" echo "arr$COUNTER[4] = ${arr$COUNTER[4]}" echo "arr$COUNTER[5] = ${arr$COUNTER[5]}" let COUNTER=COUNTER+1 echo done echo "The End" echo 

Voici le résultat:

 Nombre total de lignes 2

 La valeur du countur est 1
 Champ = 10 20 30 40 50 60
 ./sort.sh: ligne 12: arr $ COUNTER [0] = $ {arr $ COUNTER [0]}: mauvaise substitution
 La fin

Qu'est-ce qui devrait être changé / corrigé afin de le faire fonctionner correctement?

merci!

Quelques idées:

  1. Une "expansion de paramètre" d'une valeur de variable (la partie $ {…}):

     echo "arr$COUNTER[0] = ${arr$COUNTER[0]}" 

    ne fonctionnera pas. Vous pouvez vous déplacer en utilisant eval (mais je ne le recommand pas):

     eval echo "arr$COUNTER[0] = \${arr$COUNTER[0]}" 

    Cette ligne pourrait être écrite comme ceci:

     i="arr$COUNTER[0]"; echo "$i = ${!i}" 

    C'est ce qu'on appelle indirection (le!) Dans Bash.

  2. Un problème similaire se produit avec cette ligne:

     declare -a "arr$COUNTER=($field)" 

    Ce qui devrait être divisé en deux lignes, et eval utilisé:

     declare -a "arr$COUNTER" eval arr$COUNTER\=\( \$field \) 

    Encore une fois, je ne recommand pas d'utiliser eval (dans ce cas).

  3. Comme vous lisez le file entier dans la memory du shell, nous pouvons aussi utiliser une méthode plus simple pour get toutes les lignes dans un tableau:

     readarray -t lines <"VALUES_FILE.txt" 

    Cela devrait être plus rapide que d'appeler awk pour chaque ligne.

Un script avec tout ce qui précède pourrait être:

 #!/bin/bash valfile="VALUES_FILE.txt" readarray -t lines <"$valfile" ### read all lines in. line_count="${#lines[@]}" echo "Total number of lines $line_count" for ((l=0;l<$line_count;l++)); do echo "Counter value is $l" ### In which line are we? echo "Field = ${lines[l]}" ### kepth only to help understanding. k="arr$l" ### Build the variable arr$COUNTER IFS=" " read -ra $k <<<"${lines[l]}" ### Split into an array a line. eval max=\${#$k[@]} ### How many elements arr$COUNTER has? #echo "field $field and k=$k max=$max" ### Un-quote to "see" inside. for ((j=0;j<$max;j++)); do ### for each element in the line. i="$k[$j]"; echo "$i = ${!i}" ### echo it's value. done done echo "The End" echo 

Cependant, AWK peut être plus rapide, si nous pouvions exécuter ce dont vous avez besoin dans AWK.


Un traitement similaire pourrait être fait dans awk. En supposant que les 6 valeurs seront utilisées comme IP (4 d'entre elles) et les deux autres sont un nombre et une époque.

Juste un exemple très simple d'un script AWK:

 #!/bin/sh valfile="VALUES_FILE.txt" awk ' NF==6 { printf ( "IP: %s.%s.%s.%s\t",$1,$2,$3,$4) printf ( "number: %s\t",$5+2) printf ( "epoch: %s\t",$6) printf ( "\n" ) } ' "$valfile" 

Juste faire une nouvelle question avec les détails.

Vous pouvez utiliser l'indirection de variable si vous affectez le nom et l'index à une variable:

 s="arr$COUNTER[0]" echo "arr$COUNTER[0] = ${!s}" 

Vous pouvez générer des noms en utilisant eval , par exemple,

 eval declare -a '"arr'$COUNTER'=($field)"' 

en citant essentiellement tous les méta-caractères sauf ceux que vous voulez évaluer.

Donc … si $COUNTER vaut 1, votre script ferait

 declare -a "arr1=($field)" 

Pour en savoir plus:

  • command eval dans Bash et ses utilisations typiques
  • Quelle est la command "eval" dans bash?