Ce que je veux faire, c'est suivre. Dans une fonction, je dois attribuer une valeur à une variable dont le nom provient d'une autre variable. En d'autres termes:
func() {
#
# Here happens something that ultimately makes $arg="var_name"
#
declare -g ${arg}=5
}
func
echo ${var_name}; # Prints out "5"
L'extrait de code ci-dessus fonctionne parfaitement dans bash 4.2. Cependant, dans les versions antérieures à 4.2, declare
ne dispose pas de l'option -g
. Tout ce que j'ai trouvé sur Google indique que pour définir la variable globale dans une fonction, je devrais simplement utiliser la syntaxe var=value
, mais malheureusement, var
dépend lui-même d'une autre variable. ${arg}=5
ne fonctionne pas non plus. (On dit -bash: var_name=5: command not found
.
Pour les curieux, la raison en est que cette fonction crée en fait des variables globales à partir des paramètres de script. Par exemple, l'exécution de script --arg1=val
crée automatiquement la variable nommée arg1
avec la valeur val
. Enregistre des tonnes de code standard.
Vous pouvez construire votre var = valeur sous forme de chaîne et l'évaluer à l'aide de la commande intégrée bash eval
.
declare
à l'intérieur d'une fonction ne fonctionne pas comme prévu . J'avais besoin de variables globales en lecture seule déclarées dans une fonction . J'ai essayé ceci à l'intérieur d'une fonction mais cela n'a pas fonctionné:
declare -r MY_VAR=1
Mais cela n'a pas fonctionné. L'utilisation de la commande readonly
a:
func() {
readonly MY_VAR=1
}
func
echo $MY_VAR
MY_VAR=2
Ceci affichera 1 et donnera l’erreur "MY_VAR: variable en lecture seule" pour la deuxième affectation.
Etant donné que cette balise porte la balise Shell
, il est important de noter que declare
est un mot clé valide uniquement dans un ensemble limité de shells. Par conséquent, s'il prend en charge -g est sans objet. Pour faire ce genre de chose dans un Bourne Shell générique, vous pouvez simplement utiliser eval:
eval ${arg}=5
Je pense que vous avez besoin de la variable printf
avec son commutateur -v
:
func() {
printf -v "$var" '5'
}
var=var_name
func
echo "$var_name"
affichera 5
.
L'utilisation de "eval" (ou de toute affectation directe) peut vous donner des maux de tête avec des caractères spéciaux (ou des problèmes d'injection de valeur, etc.).
J'ai eu beaucoup de succès en utilisant simplement "read"
$ function assign_global() {
> local arg="$1"
> IFS="" read -d "" $arg <<<"$2"
>}
$ assign_global MYVAR 23
echo $MYVAR
23
$ assign_global MYVAR "\"'"
"'
Si vous voulez quelque chose d'un peu moins hackish, essayez d'utiliser export
à la place de declare -g
. Il a l'avantage supplémentaire d'être une variable d'environnement maintenant.
func() {
#
# Here happens something that ultimately makes $arg="var_name"
#
export ${arg}=5
}
func
echo ${var_name}; # Prints out "5"
Malheureusement, cela ne fonctionne toujours pas pour les tableaux.
Dans Bash pour déclarer des variables de tableau dans une définition de fonction, vous pouvez utiliser la commande local
en combinaison avec la commande eval
comme dans l'exemple suivant:
#!/bin/bash
function test
{
local -g $1
local array=( AA BB 'C C' DD)
eval ${1}='("${array[@]}")'
}
test VAR
echo VAR=${VAR[@]:1:2}
la sortie sera:
$./test.sh
VAR=BB C C
fonctionne avec: GNU bash, version 4.4.18
Eval fonctionnera avec les variables de tableau ... Il me suffisait de ne citer que la variable de tableau locale à l'intérieur de l'instruction eval.
Le texte ci-dessous lit dans un fichier (1er argument) une ligne à la fois, puis le copie dans le nom de variable transmis au deuxième argument du get_file.
get_file () {
declare -a Array=();
while read line; do
Array=("${Array[@]}" "($line)")
done < ${1}
eval ${2}='("${Array[@]}")'
unset Array
}
declare -a my_array=();
get_file /etc/myfile.conf my_array
echo ${#my_array[@]}
Vous pourriez peut-être utiliser les fonctions suivantes pour affecter dynamiquement votre variable globale dans bash (<4.2). Si> 2 arguments sont passés, la valeur sera le type de tableau . E.G
_set2globals variable_name arg1 [arg2] [arg3] [...]
La source:
# dynamically set $variable_name($1)=$values($2...) to globals scope
function _set2globals()
{
if (( $# < 2 )); then
printf "$FUNCNAME: expect at least 2 argument, but %d you given.\n" $# >&2
exit 1
fi
local ___pattern_='^[_a-zA-Z][_0-9a-zA-Z]*$'
if [[ ! $1 =~ $___pattern_ ]]; then
printf "$FUNCNAME: invalid variable name: %s.\n" "$1" >&2
exit 1
fi
local __variable__name__=$1
shift
local ___v_
local ___values_=()
while (($# > 0)); do
___v_=\'${1//"'"/"'\''"}\'
___values_=("${___values_[@]}" "$___v_") # Push to array
shift
done
eval $__variable__name__=\("${___values_[@]}"\)
}