J'ai écrit un script qui utilise des tableaux associatifs dans bash (v 4).
Cela fonctionne très bien sur ma machine locale qui utilise 4.1.5(1)-release
.
Sur la machine de production, en utilisant 4.1.0(1)-release
la ligne suivante, qui déclare le tableau assoc, échoue:
declare -A uniqjars
avec le message:
/script.sh: line 11: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
J'avais l'impression que c'était une fonction générale de bash 4?
Dans l'homme pour bash sur la machine de production, il discute de l'utilisation de -A
donc je suppose que devrait fonctionner.
Les tableaux associatifs sont créés à l'aide de
declare -A name
.
Je peux confirmer que le script utilise la bonne version de bash en imprimant la valeur de echo 'bash -version
.
Que pourrais-je faire de mal?
Assurez-vous que la version de bash est invoquée en tant qu'interpréteur en haut de votre script Shell (#!/bin/bash
ou autre) est également la version 4. Si vous faites:
bash --version
et ça vous donne la v4, faites un which bash
pour vérifier son emplacement.
Voici une solution de contournement, si vous souhaitez utiliser des caractères comme index de tableau avec bash v3:
array=(
'hello::world.'
'Nice::to meet you'
)
for index in "${array[@]}" ; do
KEY="${index%%::*}"
VALUE="${index##*::}"
echo "$KEY - $VALUE"
done
Production:
hello - world.
Nice - to meet you
Ce qui suit semble être un scénario typique sur macOS après l'installation d'un nouveau Bash avec Homebrew:
/bin/bash
est l'ancien Bash, 3.2/usr/local/bin/bash
est le nouveau Bash qui connaît les tableaux associatifs (4.0 ou plus récent)type bash
pointe vers /usr/local/bin/bash
et bash --version
est le nouveau (car il se résout en /usr/local/bin/bash --version
)Cependant, les scripts avec un #!/bin/bash
Ligne Shebang exécutée avec ./script
utilisera l'ancien Bash (le scénario de la question). Les solutions sont:
bash script
: le nouveau Bash sera utilisé. Inconvénient: vous devez toujours l'appeler comme ça.#!/usr/local/bin/bash
. Inconvénient: sur de nombreux systèmes, il n'y a pas de Bash dans /usr/local/bin
et votre script n'est plus portable.#!/usr/bin/env bash
. Ceci utilisera le premier bash
dans votre PATH
, qui devrait être le nouveau. C'est assez portable; le seul inconvénient est que vous ne savez pas exactement quel Bash sera exécuté.Voir aussi ces Q&R:
Vérifiez le shell actuel que vous utilisez avec cette cmd:
echo $Shell
Par exemple. cela pourrait dire /bin/bash
Exécutez --version
Sur ce $Shell
:
/bin/bash --version
Il peut produire quelque chose comme GNU bash, version 3.2.57(1)-release (x86_64-Apple-darwin16)
Si c'est avant la version 4, vous devrez mettre à niveau.
Vérifiez si vous disposez déjà d'un shell bash avec la version 4. Essayez d'exécuter:
bash --version
Si c'est le cas, il vous suffit de changer votre Shell par défaut en ce Shell.
Vous pouvez utiliser ces cmds pour ce faire:
Sudo bash -c 'echo /usr/local/bin/bash >> /etc/shells'
Sudo chsh -s /usr/local/bin/bash
Le premier ajoute le Shell aux shells autorisés. Le second change en fait votre Shell par défaut.
Voici comment obtenir la version bash
mise à jour sur OS X, vous devez installer brew
puis bash
.
$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-Apple-darwin14)
$ brew install bash
... install
$ /usr/local/bin/bash --version
GNU bash, version 4.3.46(1)-release (x86_64-Apple-darwin14.5.0)
meigrafd la réponse a résolu mon problème, donc si vous utilisez un Shebang incorrect ou encore sur la version 3 de bash, ce qui suit me permet de renvoyer une valeur basée sur sa clé associée:
array=(
'hello::world.'
'Nice::to meet you'
)
for index in "${array[@]}" ; do
KEY="${index%%::*}"
VALUE="${index##*::}"
if [ "$KEY" == "Nice" ]; then
echo "$VALUE"
break
fi
done
Cela renverra la valeur "pour vous rencontrer".
Rien ci-dessus ne m'a aidé, j'ai donc ouvert/etc/shells et changé la ligne - /bin/bash
à /usr/local/bin/bash
, puis l'a rechargée avec source /etc/shells
et maintenant je peux profiter de nouvelles possibilités de v4 de bash
L'ancienne version BASH ne supportait pas declare -A
syntaxe de déclaration des tableaux. Je suggère d'utiliser l'un de ces 2 formulaires pour déclarer des tableaux en bash afin de le rendre compatible avec l'ancienne version bash de votre système de production:
arr=( '10' '20' '30' )
echo ${arr[@]}
ou
arr[0]=10
arr[1]=20
arr[2]=30
echo ${arr[@]}
Par la commande:
help declare
declare: declare [-aAfFgilnrtux] [-p] [name[=value] ...]
Set variable values and attributes.
Declare variables and give them attributes. If no NAMEs are given,
display the attributes and values of all variables.
Options which are set attributes:
-a to make NAMEs indexed arrays (if supported)
-A to make NAMEs associative arrays (if supported)
Notez que "-a" en minuscule et "-A" en majuscule sont "(si pris en charge)". Aussi, si vous regardez le message d'erreur affiché pour déclarer l'utilisation:
/script.sh: line 11: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
Les options données sont "[-afFirtx]" montrant l'utilisation d'un "-a" en minuscule mais pas d'un "-A" en majuscule. Comparez cela à la chaîne d'utilisation de la commande help. Il semble que ce ne soit tout simplement pas pris en charge sur la machine donnée.
Essayez d'utiliser un Shebang différent. Sur mon Mac:
$ which bash
/usr/local/bin/bash
Donc, ce script fonctionne bien, produisant "Hello World":
#!/usr/local/bin/bash
declare -A assoc
assoc[hello]="Hello World"
echo ${assoc[hello]}