Tableaux dans Unne Bourne Shell

J'essaye d'utiliser des arrays dans Bourne shell ( /bin/sh ). J'ai trouvé que le moyen d'initialiser des éléments de tableau est:

 arr=(1 2 3) 

Mais il rencontre une erreur:

 syntax error at line 8: `arr=' unexpected 

Maintenant, le post où j'ai trouvé cette syntaxe dit que c'est pour bash , mais je n'ai pas trouvé de syntaxe séparée pour Bourne shell. La syntaxe est-elle la même pour /bin/sh ?

    /bin/sh n'est presque jamais un shell Bourne sur aucun système de nos jours (même Solaris, qui était l'un des derniers systèmes majeurs à avoir été mis sur POSIX sh pour son / bin / sh dans Solaris 11). /bin/sh était la coquille Thompson au début des années 70. La shell Bourne l'a remplacé dans Unix V7 en 1979.

    /bin/sh a été la shell Bourne pendant de nombreuses années par la suite (ou la shell Almquist, une ré-implémentation gratuite sur les BSD).

    De nos jours, /bin/sh est plus communément un interpréteur ou un autre pour le langage POSIX sh qui est lui-même un sous-set du langage de ksh88 (et un sur-set du langage shell Bourne avec quelques incompatibilités).

    Le shell Bourne ou la spécification du langage POSIX sh ne prennent pas en charge les arrays. Ou plutôt, ils n'ont qu'un seul tableau: les parameters positionnels ( $1 , $2 , $@ , donc un tableau par fonction aussi).

    ksh88 avait des arrays que vous définissez avec set -A , mais cela n'a pas été spécifié dans POSIX sh car la syntaxe est gênante et peu utilisable.

    Les autres shells avec des variables array / lists sont les suivantes: csh / tcsh , rc , es , bash (qui copiait principalement la syntaxe ksh la façon ksh93), yash , zsh , fish avec une syntaxe différente successeur d'Unix, fish et zsh étant les plus cohérents) …

    En standard sh (fonctionne également dans les versions modernes de la shell Bourne):

     set '1st element' 2 3 # setting the array set -- "$@" more # adding elements to the end of the array shift 2 # removing elements (here 2) from the beginning of the array printf '<%s>\n' "$@" # passing all the elements of the $@ array # as arguments to a command for i do # looping over the elements of the $@ array ($1, $2...) printf 'Looping over "%s"\n' "$i" done printf '%s\n' "$1" # accessing individual element of the array. # up to the 9th only with the Bourne shell though # (only the Bourne shell), and note that you need # the braces (as in "${10}") past the 9th in other # shells. printf '%s\n' "$# elements in the array" printf '%s\n' "$*" # join the elements of the array with the # first character (byte in some implementations) # of $IFS (not in the Bourne shell where it's on # space instead regardless of the value of $IFS) 

    (notez que dans le shell Bourne, $IFS doit contenir le caractère espace pour "$@" pour fonctionner correctement (un bug), et vous ne pouvez pas accéder aux éléments au dessus de $9 ( ${10} ne fonctionnera pas shift 1; echo "$9" faites shift 1; echo "$9" ou bouclez-les)).

    Il n'y a pas de arrays dans la shell Bourne. Vous pouvez utiliser la méthode suivante pour créer un tableau et le parcourir:

     #!/bin/sh # ARRAY.sh: example usage of arrays in Bourne Shell array_traverse() { for i in $(seq 1 $2) do current_value=$1$i echo $(eval echo \$$current_value) done return 1 } ARRAY_1=one ARRAY_2=two ARRAY_3=333 array_traverse ARRAY_ 3 

    Peu importe la façon d'utiliser les arrays dans sh , vous choisirez, il sera toujours encombrant. Envisagez d'utiliser un langage différent comme Python ou Perl si vous le pouvez à less que vous ne soyez bloqué avec une plate-forme très limitée ou que vous vouliez apprendre quelque chose.

    Comme les autres l'ont dit, le Bourne Shell n'a pas de véritables arrays.

    Cependant, en fonction de ce que vous devez faire, les strings délimitées devraient suffire:

     sentence="I don't need arrays because I can use delimited ssortingngs" for word in $sentence do printf '%s\n' "$word" done 

    Si les délimiteurs typiques (espace, tabulation et nouvelle ligne) ne suffisent pas, vous pouvez définir IFS sur le délimiteur souhaité avant la boucle.

    Et si vous avez besoin de build le tableau par programmation, vous pouvez simplement créer une string délimitée.

    Une façon de simuler des arrays dans le tableau de bord (elle peut être adaptée à un nombre quelconque de dimensions d'un tableau): (Veuillez noter que l'utilisation de la command seq exige que IFS soit réglé sur '' (SPACE = la valeur par défaut). utiliser while ... do ... ou do ... while ... boucle plutôt pour éviter cela (j'ai gardé seq dans le cadre d'une meilleure illustration de ce que le code fait).)

     #!/bin/sh ## The following functions implement vectors (arrays) operations in dash: ## Definition of a vector <v>: ## v_0 - variable that stores the number of elements of the vector ## v_1..v_n, where n=v_0 - variables that store the values of the vector elements VectorAddElementNext () { # Vector Add Element Next # Adds the ssortingng contained in variable $2 in the next element position (vector length + 1) in vector $1 local elem_value local vector_length local elem_name eval elem_value=\"\$$2\" eval vector_length=\$$1\_0 if [ -z "$vector_length" ]; then vector_length=$((0)) fi vector_length=$(( vector_length + 1 )) elem_name=$1_$vector_length eval $elem_name=\"\$elem_value\" eval $1_0=$vector_length } VectorAddElementDVNext () { # Vector Add Element Direct Value Next # Adds the ssortingng $2 in the next element position (vector length + 1) in vector $1 local elem_value local vector_length local elem_name eval elem_value="$2" eval vector_length=\$$1\_0 if [ -z "$vector_length" ]; then vector_length=$((0)) fi vector_length=$(( vector_length + 1 )) elem_name=$1_$vector_length eval $elem_name=\"\$elem_value\" eval $1_0=$vector_length } VectorAddElement () { # Vector Add Element # Adds the ssortingng contained in the variable $3 in the position contained in $2 (variable or direct value) in the vector $1 local elem_value local elem_position local vector_length local elem_name eval elem_value=\"\$$3\" elem_position=$(($2)) eval vector_length=\$$1\_0 if [ -z "$vector_length" ]; then vector_length=$((0)) fi if [ $elem_position -ge $vector_length ]; then vector_length=$elem_position fi elem_name=$1_$elem_position eval $elem_name=\"\$elem_value\" if [ ! $elem_position -eq 0 ]; then eval $1_0=$vector_length fi } VectorAddElementDV () { # Vector Add Element # Adds the ssortingng $3 in the position $2 (variable or direct value) in the vector $1 local elem_value local elem_position local vector_length local elem_name eval elem_value="$3" elem_position=$(($2)) eval vector_length=\$$1\_0 if [ -z "$vector_length" ]; then vector_length=$((0)) fi if [ $elem_position -ge $vector_length ]; then vector_length=$elem_position fi elem_name=$1_$elem_position eval $elem_name=\"\$elem_value\" if [ ! $elem_position -eq 0 ]; then eval $1_0=$vector_length fi } VectorPrint () { # Vector Print # Prints all the elements names and values of the vector $1 on sepparate lines local vector_length vector_length=$(($1_0)) if [ "$vector_length" = "0" ]; then echo "Vector \"$1\" is empty!" else echo "Vector \"$1\":" for i in $(seq 1 $vector_length); do eval echo \"[$i]: \\\"\$$1\_$i\\\"\" ###OR: eval printf \'\%s\\\n\' \"[\$i]: \\\"\$$1\_$i\\\"\" done fi } VectorDestroy () { # Vector Destroy # Empties all the elements values of the vector $1 local vector_length vector_length=$(($1_0)) if [ ! "$vector_length" = "0" ]; then for i in $(seq 1 $vector_length); do unset $1_$i done unset $1_0 fi } ################## ### MAIN START ### ################## ## Setting vector 'params' with all the parameters received by the script: for i in $(seq 1 $#); do eval param="\${$i}" VectorAddElementNext params param done # Printing the vector 'params': VectorPrint params read temp ## Setting vector 'params2' with the elements of the vector 'params' in reversed order: if [ -n "$params_0" ]; then for i in $(seq 1 $params_0); do count=$((params_0-i+1)) VectorAddElement params2 count params_$i done fi # Printing the vector 'params2': VectorPrint params2 read temp ## Getting the values of 'params2'`s elements and printing them: if [ -n "$params2_0" ]; then echo "Printing the elements of the vector 'params2':" for i in $(seq 1 $params2_0); do eval current_elem_value=\"\$params2\_$i\" echo "params2_$i=\"$current_elem_value\"" done else echo "Vector 'params2' is empty!" fi read temp ## Creating a two dimensional array ('a'): for i in $(seq 1 10); do VectorAddElement a 0 i for j in $(seq 1 8); do value=$(( 8 * ( i - 1 ) + j )) VectorAddElementDV a_$i $j $value done done ## Manually printing the two dimensional array ('a'): echo "Printing the two-dimensional array 'a':" if [ -n "$a_0" ]; then for i in $(seq 1 $a_0); do eval current_vector_lenght=\$a\_$i\_0 if [ -n "$current_vector_lenght" ]; then for j in $(seq 1 $current_vector_lenght); do eval value=\"\$a\_$i\_$j\" printf "$value " done fi printf "\n" done fi ################ ### MAIN END ### ################