Passer des tableaux en tant que paramètres dans bash


197

Comment puis-je passer un tableau en tant que paramètre à une fonction bash?

Remarque: après n'avoir pas trouvé de réponse ici sur Stack Overflow, j'ai publié moi-même ma solution un peu brute. Il ne permet qu'un seul tableau soit passé, et c'est le dernier élément de la liste de paramètres. En fait, il ne passe pas du tout le tableau, mais une liste de ses éléments, qui sont réassemblés dans un tableau par called_function(), mais cela a fonctionné pour moi. Si quelqu'un connaît un meilleur moyen, n'hésitez pas à l'ajouter ici.


1
Ici vous avez de belles références et des tonnes d'exemples.
Artem Barger

17
Euh ... Trois votes négatifs sur une question de cinq ans dans la même minute?
DevSolar

Réponses:


226

Vous pouvez passer plusieurs tableaux comme arguments en utilisant quelque chose comme ceci:

takes_ary_as_arg()
{
    declare -a argAry1=("${!1}")
    echo "${argAry1[@]}"

    declare -a argAry2=("${!2}")
    echo "${argAry2[@]}"
}
try_with_local_arys()
{
    # array variables could have local scope
    local descTable=(
        "sli4-iread"
        "sli4-iwrite"
        "sli3-iread"
        "sli3-iwrite"
    )
    local optsTable=(
        "--msix  --iread"
        "--msix  --iwrite"
        "--msi   --iread"
        "--msi   --iwrite"
    )
    takes_ary_as_arg descTable[@] optsTable[@]
}
try_with_local_arys

fera écho:

sli4-iread sli4-iwrite sli3-iread sli3-iwrite  
--msix  --iread --msix  --iwrite --msi   --iread --msi   --iwrite

Modifier / notes: (à partir des commentaires ci-dessous)

  • descTableet optsTablesont passés en tant que noms et sont développés dans la fonction. Ainsi, aucun $n'est nécessaire lorsqu'il est donné comme paramètres.
  • Notez que cela fonctionne toujours même si descTableetc est défini avec local, car les locaux sont visibles par les fonctions qu'ils appellent.
  • Le !in ${!1}développe la variable arg 1.
  • declare -a rend simplement le tableau indexé explicite, ce n'est pas strictement nécessaire.

14
Une chose à noter est que si le tableau d'origine est clairsemé, le tableau de la fonction de réception n'aura pas les mêmes indices.
Suspendu jusqu'à nouvel ordre.

13
C'est génial, mais Ken ou quelqu'un peut-il expliquer quelques choses qui me déconcertent sur les raisons de son fonctionnement: 1 - J'aurais pensé que descTable et optsTable auraient dû être préfixés avec $ lorsqu'ils étaient passés comme arguments de fonction. 2 - Dans la première ligne de "prend ...", pourquoi une déclaration de tableau explicite est-elle nécessaire? 3 - Et qu'est-ce que le! signifie dans l'expression $ {! 1}, et pourquoi [@] n'est-il pas obligatoire ou même autorisé? - Cela fonctionne, et tous ces détails semblent nécessaires en fonction de mes tests, mais j'aimerais comprendre pourquoi!
Jan Hettich

8
1: descTable et optsTable sont juste passés comme noms, donc il n'y a pas de $, ils ne seront développés que dans la fonction appelée 2: pas totalement sûr, mais je pense que ce n'est pas vraiment nécessaire 3: le! est utilisé car les paramètres passés à la fonction doivent être développés deux fois: $ 1 se développe en "descTable [@]", et cela doit être développé en "$ {descTable [@]}". C'est exactement ce que fait la syntaxe $ {! 1}.
Elmar Zander

8
Je ne pense pas que la partie "declare -a" soit nécessaire. L'existence de parenthèses définit déjà la LHS de l'affectation comme un tableau.
Erik Aronesty

3
Cette réponse m'a aidé à résoudre un problème à l'instant. Cependant, je voulais souligner que sur ma machine (en utilisant bash 4.3.42), les guillemets "$ {! 1}" et "$ {! 2}" doivent être supprimés. Si vous ne le faites pas, la valeur du tableau d'origine est lue comme une chaîne et affectée respectivement à argAry1 [0] et argAry2 [0], ce qui signifie essentiellement que la structure du tableau est perdue.
user.friendly

87

Remarque: C'est la solution un peu brute que j'ai publiée moi-même, après n'avoir pas trouvé de réponse ici sur Stack Overflow. Il ne permet qu'un seul tableau soit passé, et c'est le dernier élément de la liste de paramètres. En fait, il ne passe pas du tout le tableau, mais une liste de ses éléments, qui sont réassemblés dans un tableau par called_function (), mais cela a fonctionné pour moi. Un peu plus tard, Ken a posté sa solution, mais j'ai gardé la mienne ici pour référence "historique".

calling_function()
{
    variable="a"
    array=( "x", "y", "z" )
    called_function "${variable}" "${array[@]}"
}

called_function()
{
    local_variable="${1}"
    shift
    local_array=("${@}")
}

19
Trois ans après les faits, cette réponse - conservée uniquement pour des raisons historiques - a reçu deux votes défavorables en quelques jours. Comme malheureusement d'habitude sur SO, sans aucune note sur les raisons pour lesquelles les gens pensent que cela est justifié. Notez que cette réponse est antérieure à toutes les autres et que j'ai accepté la réponse de Ken comme la meilleure solution. Je suis parfaitement conscient qu'il est loin d'être parfait, mais pendant quatre mois, c'était le meilleur disponible sur SO. Pourquoi il devrait être déclassé deux ans après avoir pris la deuxième place pour la solution parfaite de Ken me dépasse.
DevSolar

@geirha: Je vous demanderais de vérifier qui a posté la question, qui a publié cette réponse et qui a probablement accepté la réponse que vous qualifiez de «mauvaise». ;-) Vous voudrez peut-être aussi vérifier la note dans la question, qui montre pourquoi cette solution est inférieure à celle de Ken.
DevSolar

2
Je sais que vous avez posé la question, que vous avez rédigé cette réponse et que vous avez accepté la mauvaise réponse. C'est pourquoi je l'ai formulé de cette façon. La raison pour laquelle la réponse acceptée est mauvaise est qu'elle essaie de passer un tableau par référence, ce que vous devriez vraiment éviter. De plus, l'exemple écrase plusieurs arguments en une seule chaîne. Si vous avez vraiment besoin de passer des tableaux par référence, bash n'est pas le bon langage pour commencer. Même avec les nouvelles variables nameref de bash 4.3, vous ne pouvez pas éviter en toute sécurité les collisions de noms (référence circulaire).
geirha

5
Eh bien, vous pouvez transmettre plusieurs tableaux si vous incluez le nombre d'éléments de chaque tableau. called_function "${#array[@]}" "${array[@]}" "${#array2[@]}" "${array2[@]}"etc ... toujours avec des restrictions évidentes, mais vraiment, mieux vaut résoudre le problème d'une manière prise en charge par la langue, plutôt que d'essayer de plier la langue pour qu'elle fonctionne comme vous en avez l'habitude dans d'autres langues.
geirha

1
@geirha: Eh bien, je suppose que nous devrons convenir que nous ne sommes pas d'accord, et vous devrez me laisser juger quelle réponse répond le mieux à ma question. Personnellement, je préfère de toute façon passer des tableaux par référence (peu importe la langue, pour sauvegarder la copie des données); encore plus lorsque l'alternative est de se pencher en arrière et de passer la taille du tableau comme paramètre supplémentaire ...
DevSolar

38

Commentant la solution de Ken Bertelson et répondant à Jan Hettich:

Comment ça fonctionne

la takes_ary_as_arg descTable[@] optsTable[@]ligne en try_with_local_arys()fonction envoie:

  1. Cela crée en fait une copie des tableaux descTableet optsTablequi sont accessibles à la takes_ary_as_argfonction.
  2. takes_ary_as_arg()fonction reçoit descTable[@]et optsTable[@]sous forme de chaînes, cela signifie $1 == descTable[@]et $2 == optsTable[@].
  3. au début de la takes_ary_as_arg()fonction, il utilise la ${!parameter}syntaxe, qui est appelée référence indirecte ou parfois double référence , cela signifie qu'au lieu d'utiliser $1la valeur de, nous utilisons la valeur de la valeur développée de$1 , exemple:

    baba=booba
    variable=baba
    echo ${variable} # baba
    echo ${!variable} # booba
    

    de même pour $2.

  4. mettre cela dans argAry1=("${!1}")crée argAry1comme un tableau (les crochets suivants =) avec le développé descTable[@], tout comme écrire ici argAry1=("${descTable[@]}")directement. le declareil n'est pas nécessaire.

NB: Il est à noter que l'initialisation du tableau à l'aide de cette forme de parenthèse initialise le nouveau tableau en fonction du IFSou du séparateur de champ interne qui est par défaut tab , nouvelle ligne et espace . dans ce cas, puisqu'il utilise la [@]notation, chaque élément est vu par lui-même comme s'il était cité (contrairement à [*]).

Ma réservation avec

Dans BASH, la portée de la variable locale est la fonction courante et chaque fonction enfant appelée à partir de celle-ci, cela se traduit par le fait que la takes_ary_as_arg()fonction "voit" ceux-ci descTable[@]et les optsTable[@]tableaux, donc cela fonctionne (voir l'explication ci-dessus).

Dans ce cas, pourquoi ne pas examiner directement ces variables elles-mêmes? C'est comme écrire là-bas:

argAry1=("${descTable[@]}")

Voir l'explication ci-dessus, qui copie simplement descTable[@]les valeurs du tableau en fonction du courant IFS.

En résumé

Cela ne passe, en substance, rien par valeur - comme d'habitude.

Je tiens également à souligner le commentaire de Dennis Williamson ci-dessus: les tableaux clairsemés (tableaux sans toutes les clés définies - avec des "trous" en eux) ne fonctionneront pas comme prévu - nous perdrions les clés et "condenserions" le tableau.

Cela étant dit, je vois la valeur de la généralisation, les fonctions peuvent donc obtenir les tableaux (ou copies) sans connaître les noms:

  • pour ~ "copies": cette technique est assez bonne, il suffit de garder à l'esprit que les indices (clés) ont disparu.
  • pour les copies réelles: on peut utiliser un eval pour les clés, par exemple:

    eval local keys=(\${!$1})
    

puis une boucle les utilisant pour créer une copie. Remarque: ici !n'est pas utilisé lors de l'évaluation indirecte / double précédente, mais plutôt dans le contexte d'un tableau, il renvoie les indices du tableau (clés).

  • et, bien sûr, si nous devions passer descTableet des optsTablechaînes (sans [@]), nous pourrions utiliser le tableau lui-même (comme par référence) avec eval. pour une fonction générique qui accepte des tableaux.

2
Bonnes explications du mécanisme derrière l'explication de Ken Bertelson. A la question "Dans ce cas, pourquoi ne pas regarder directement ces variables elles-mêmes?", Je répondrai: simplement pour la réutilisation de la fonction. Disons que j'ai besoin d'appeler une fonction avec Array1, puis avec Array2, passer les noms de tableau devient pratique.
gfrigon

23

Le problème de base ici est que le (s) développeur (s) de bash qui a conçu / implémenté des tableaux ont vraiment vissé le chien. Ils ont décidé que ${array}c'était juste une main courte ${array[0]}, ce qui était une grave erreur. Surtout lorsque vous considérez que cela ${array[0]}n'a pas de sens et que vous évaluez la chaîne vide si le type de tableau est associatif.

L'affectation d'un tableau prend la forme array=(value1 ... valueN)où value a la syntaxe [subscript]=string, affectant ainsi une valeur directement à un index particulier du tableau. Cela fait qu'il peut y avoir deux types de tableaux, indexés numériquement et indexés par hachage (appelés tableaux associatifs en langage bash). Cela permet également de créer des tableaux à indexation numérique clairsemés. Laisser la [subscript]=partie est abrégé pour un tableau indexé numériquement, en commençant par l'indice ordinal de 0 et en incrémentant à chaque nouvelle valeur dans l'instruction d'affectation.

Par conséquent, ${array}devrait évaluer le tableau entier , les index et tout. Il doit être évalué à l'inverse de l'instruction d'affectation. Toute majeure de troisième année en CS devrait le savoir. Dans ce cas, ce code fonctionnerait exactement comme vous pouvez vous y attendre:

declare -A foo bar
foo=${bar}

Ensuite, passer des tableaux par valeur aux fonctions et assigner un tableau à un autre fonctionnerait comme le reste de la syntaxe du shell. Mais comme ils n'ont pas fait cela correctement, l'opérateur d'affectation =ne fonctionne pas pour les tableaux, et les tableaux ne peuvent pas être passés par valeur à des fonctions ou à des sous-shell ou à une sortie en général ( echo ${array}) sans code pour tout mâcher.

Donc, si cela avait été fait correctement, l'exemple suivant montrerait comment l'utilité des tableaux dans bash pourrait être nettement meilleure:

simple=(first=one second=2 third=3)
echo ${simple}

la sortie résultante doit être:

(first=one second=2 third=3)

Ensuite, les tableaux pourraient utiliser l'opérateur d'affectation et être passés par valeur aux fonctions et même à d'autres scripts shell. Facilement stocké en sortant dans un fichier, et facilement chargé d'un fichier dans un script.

declare -A foo
read foo <file

Hélas, nous avons été déçus par une équipe de développement de bash par ailleurs superlative.

En tant que tel, pour passer un tableau à une fonction, il n'y a vraiment qu'une seule option, et c'est d'utiliser la fonctionnalité nameref:

function funky() {
    local -n ARR

    ARR=$1
    echo "indexes: ${!ARR[@]}"
    echo "values: ${ARR[@]}"
}

declare -A HASH

HASH=([foo]=bar [zoom]=fast)
funky HASH # notice that I'm just passing the word 'HASH' to the function

entraînera la sortie suivante:

indexes: foo zoom
values: bar fast

Comme cela passe par référence, vous pouvez également attribuer au tableau dans la fonction. Oui, le tableau référencé doit avoir une portée globale, mais cela ne devrait pas être trop gros, étant donné qu'il s'agit d'un script shell. Pour passer un tableau indexé associatif ou clairsemé par valeur à une fonction, il faut lancer tous les index et les valeurs sur la liste d'arguments (pas trop utile s'il s'agit d'un grand tableau) sous forme de chaînes simples comme celle-ci:

funky "${!array[*]}" "${array[*]}"

puis écrire un tas de code à l'intérieur de la fonction pour réassembler le tableau.


1
La solution d'utilisation local -nest meilleure et plus à jour que la réponse acceptée. Cette solution fonctionnera également pour une variable de tout type. L'exemple répertorié dans cette réponse peut être abrégé en local -n ARR=${1}. Cependant, l' -noption pour local/ declaren'est disponible que dans les versions 4.3 et supérieures de Bash.
richardjsimkins

C'est sympa! Petit hic: si vous passez une variable avec le même nom que l'argument local de votre fonction (par exemple funky ARR), le shell donnera un avertissement circular name reference, car fondamentalement la fonction essaiera de faire local -n ARR=ARR. Bonne discussion sur ce sujet.
Gene Pavlovsky

5

La réponse de DevSolar a un point que je ne comprends pas (peut-être qu'il a une raison spécifique de le faire, mais je ne peux pas penser à une seule): il définit le tableau à partir des paramètres de position élément par élément, itératif.

Une approche plus facile serait

called_function()
{
  ...
  # do everything like shown by DevSolar
  ...

  # now get a copy of the positional parameters
  local_array=("$@")
  ...
}

1
La raison pour laquelle je ne le fais pas est que je n'ai pas du tout joué avec les tableaux bash jusqu'à il y a quelques jours. Auparavant, je serais passé à Perl si cela devenait complexe, une option que je n'ai pas dans mon travail actuel. Merci pour l'indice!
DevSolar

4

Un moyen simple de passer plusieurs tableaux en tant que paramètre consiste à utiliser une chaîne séparée par des caractères. Vous pouvez appeler votre script comme ceci:

./myScript.sh "value1;value2;value3" "somethingElse" "value4;value5" "anotherOne"

Ensuite, vous pouvez l'extraire dans votre code comme ceci:

myArray=$1
IFS=';' read -a myArray <<< "$myArray"

myOtherArray=$3
IFS=';' read -a myOtherArray <<< "$myOtherArray"

De cette façon, vous pouvez réellement passer plusieurs tableaux en tant que paramètres et il n'est pas nécessaire que ce soit les derniers paramètres.


3
function aecho {
  set "$1[$2]"
  echo "${!1}"
}

Exemple

$ foo=(dog cat bird)

$ aecho foo 1
cat

1

Celui-ci fonctionne même avec des espaces:

format="\t%2s - %s\n"

function doAction
{
  local_array=("$@")
  for (( i = 0 ; i < ${#local_array[@]} ; i++ ))
    do
      printf "${format}" $i "${local_array[$i]}"
  done
  echo -n "Choose: "
  option=""
  read -n1 option
  echo ${local_array[option]}
  return
}

#the call:
doAction "${tools[@]}"

2
Je me demande quel est le point ici. C'est juste un argument normal qui passe. La syntaxe "$ @" est faite pour fonctionner pour les espaces: "$ @" équivaut à "$ 1" "$ 2" ...
Andreas Spindler

Puis-je passer 2 tableaux à une fonction?
pihentagy

1

Avec quelques astuces, vous pouvez réellement passer des paramètres nommés aux fonctions, avec des tableaux.

La méthode que j'ai développée vous permet d'accéder aux paramètres passés à une fonction comme celle-ci:

testPassingParams() {

    @var hello
    l=4 @array anArrayWithFourElements
    l=2 @array anotherArrayWithTwo
    @var anotherSingle
    @reference table   # references only work in bash >=4.3
    @params anArrayOfVariedSize

    test "$hello" = "$1" && echo correct
    #
    test "${anArrayWithFourElements[0]}" = "$2" && echo correct
    test "${anArrayWithFourElements[1]}" = "$3" && echo correct
    test "${anArrayWithFourElements[2]}" = "$4" && echo correct
    # etc...
    #
    test "${anotherArrayWithTwo[0]}" = "$6" && echo correct
    test "${anotherArrayWithTwo[1]}" = "$7" && echo correct
    #
    test "$anotherSingle" = "$8" && echo correct
    #
    test "${table[test]}" = "works"
    table[inside]="adding a new value"
    #
    # I'm using * just in this example:
    test "${anArrayOfVariedSize[*]}" = "${*:10}" && echo correct
}

fourElements=( a1 a2 "a3 with spaces" a4 )
twoElements=( b1 b2 )
declare -A assocArray
assocArray[test]="works"

testPassingParams "first" "${fourElements[@]}" "${twoElements[@]}" "single with spaces" assocArray "and more... " "even more..."

test "${assocArray[inside]}" = "adding a new value"

En d'autres termes, non seulement vous pouvez appeler vos paramètres par leurs noms (ce qui constitue un noyau plus lisible), mais vous pouvez en fait passer des tableaux (et des références à des variables - cette fonctionnalité ne fonctionne que dans bash 4.3 cependant)! De plus, les variables mappées sont toutes dans la portée locale, tout comme $ 1 (et autres).

Le code qui fait ce travail est assez léger et fonctionne à la fois dans bash 3 et bash 4 (ce sont les seules versions avec lesquelles je l'ai testé). Si vous êtes intéressé par d'autres astuces comme celle-ci qui rendent le développement avec bash beaucoup plus agréable et plus facile, vous pouvez jeter un œil à mon Bash Infinity Framework , le code ci-dessous a été développé à cet effet.

Function.AssignParamLocally() {
    local commandWithArgs=( $1 )
    local command="${commandWithArgs[0]}"

    shift

    if [[ "$command" == "trap" || "$command" == "l="* || "$command" == "_type="* ]]
    then
        paramNo+=-1
        return 0
    fi

    if [[ "$command" != "local" ]]
    then
        assignNormalCodeStarted=true
    fi

    local varDeclaration="${commandWithArgs[1]}"
    if [[ $varDeclaration == '-n' ]]
    then
        varDeclaration="${commandWithArgs[2]}"
    fi
    local varName="${varDeclaration%%=*}"

    # var value is only important if making an object later on from it
    local varValue="${varDeclaration#*=}"

    if [[ ! -z $assignVarType ]]
    then
        local previousParamNo=$(expr $paramNo - 1)

        if [[ "$assignVarType" == "array" ]]
        then
            # passing array:
            execute="$assignVarName=( \"\${@:$previousParamNo:$assignArrLength}\" )"
            eval "$execute"
            paramNo+=$(expr $assignArrLength - 1)

            unset assignArrLength
        elif [[ "$assignVarType" == "params" ]]
        then
            execute="$assignVarName=( \"\${@:$previousParamNo}\" )"
            eval "$execute"
        elif [[ "$assignVarType" == "reference" ]]
        then
            execute="$assignVarName=\"\$$previousParamNo\""
            eval "$execute"
        elif [[ ! -z "${!previousParamNo}" ]]
        then
            execute="$assignVarName=\"\$$previousParamNo\""
            eval "$execute"
        fi
    fi

    assignVarType="$__capture_type"
    assignVarName="$varName"
    assignArrLength="$__capture_arrLength"
}

Function.CaptureParams() {
    __capture_type="$_type"
    __capture_arrLength="$l"
}

alias @trapAssign='Function.CaptureParams; trap "declare -i \"paramNo+=1\"; Function.AssignParamLocally \"\$BASH_COMMAND\" \"\$@\"; [[ \$assignNormalCodeStarted = true ]] && trap - DEBUG && unset assignVarType && unset assignVarName && unset assignNormalCodeStarted && unset paramNo" DEBUG; '
alias @param='@trapAssign local'
alias @reference='_type=reference @trapAssign local -n'
alias @var='_type=var @param'
alias @params='_type=params @param'
alias @array='_type=array @param'

1

Juste pour ajouter à la réponse acceptée, car j'ai trouvé que cela ne fonctionne pas bien si le contenu du tableau ressemble à quelque chose comme:

RUN_COMMANDS=(
  "command1 param1... paramN"
  "command2 param1... paramN"
)

Dans ce cas, chaque membre du tableau est divisé, donc le tableau que la fonction voit est équivalent à:

RUN_COMMANDS=(
    "command1"
    "param1"
     ...
    "command2"
    ...
)

Pour que ce cas fonctionne, la façon dont j'ai trouvé est de passer le nom de la variable à la fonction, puis d'utiliser eval:

function () {
    eval 'COMMANDS=( "${'"$1"'[@]}" )'
    for COMMAND in "${COMMANDS[@]}"; do
        echo $COMMAND
    done
}

function RUN_COMMANDS

Juste mon 2 ©


1

Aussi laid soit-il, voici une solution de contournement qui fonctionne tant que vous ne passez pas un tableau explicitement, mais une variable correspondant à un tableau:

function passarray()
{
    eval array_internally=("$(echo '${'$1'[@]}')")
    # access array now via array_internally
    echo "${array_internally[@]}"
    #...
}

array=(0 1 2 3 4 5)
passarray array # echo's (0 1 2 3 4 5) as expected

Je suis sûr que quelqu'un peut proposer une implémentation plus claire de l'idée, mais j'ai trouvé que c'était une meilleure solution que de passer un tableau en tant "{array[@]"}que puis d'y accéder en interne array_inside=("$@"). Cela devient compliqué lorsqu'il y a d'autres getoptsparamètres / positionnels . Dans ces cas, j'ai d'abord dû déterminer, puis supprimer les paramètres non associés au tableau en utilisant une combinaison de shiftsuppression d'élément de tableau.

Une perspective puriste considère probablement cette approche comme une violation du langage, mais pragmatiquement parlant, cette approche m'a évité beaucoup de chagrin. Sur un sujet connexe, j'utilise également evalpour attribuer un tableau construit en interne à une variable nommée en fonction d'un paramètre que target_varnameje passe à la fonction:

eval $target_varname=$"(${array_inside[@]})"

J'espère que cela aide quelqu'un.


0

Condition : fonction pour trouver une chaîne dans un tableau.
Il s'agit d'une légère simplification de la solution de DevSolar en ce qu'elle utilise les arguments passés plutôt que de les copier.

myarray=('foobar' 'foxbat')

function isInArray() {
  local item=$1
  shift
  for one in $@; do
    if [ $one = $item ]; then
      return 0   # found
    fi
  done
  return 1       # not found
}

var='foobar'
if isInArray $var ${myarray[@]}; then
  echo "$var found in array"
else
  echo "$var not found in array"
fi 

0

Ma réponse courte est:

function display_two_array {
    local arr1=$1
    local arr2=$2
    for i in $arr1
    do
       "arrary1: $i"
    done
    
    for i in $arr2
    do
       "arrary2: $i"
    done
}

test_array=(1 2 3 4 5)
test_array2=(7 8 9 10 11)

display_two_array "${test_array[*]}" "${test_array2[*]}"
Il convient de noter que ${test_array[*]}et ${test_array2[*]}doit être entouré de "", sinon vous échouerez.


Votre exemple est incorrect car incomplet. Veuillez donner le code complet du script.
Dennis VR
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.