Déclarer une variable globale dans une fonction
ce que je veux faire, c'est suivre. L'intérieur d'une fonction, j'ai besoin d'assigner une valeur à une variable, dont le nom est pris 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 très bien dans bash 4.2. Cependant, à bash Avant 4.2,declare
ne pas -g
option. Tout ce que j'ai trouvé chez google dit que pour définir la variable globale à l'intérieur d'une fonction, je devrais juste utiliser le var=value
la syntaxe, mais malheureusement var
lui-même dépend d'un autre variable. ${arg}=5
ne fonctionne pas non plus. (Il est dit -bash: var_name=5: command not found
.
pour les curieux, la raison de tout cela est que cette fonction crée en fait des variables globales à partir des paramètres du script, c'est-à-dire en exécutant script --arg1=val
crée automatiquement la variable named arg1
valeur val
. Économise des tonnes de code boilerplate.
9 réponses
Vous pouvez construire votre var=valeur comme une chaîne et l'évaluer en utilisant la commande bash builtin 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é ce à l'intérieur d'une fonction, mais il ne fonctionne pas:
declare -r MY_VAR=1
Mais cela ne fonctionne pas. À l'aide de la readonly
commande:
func() {
readonly MY_VAR=1
}
func
echo $MY_VAR
MY_VAR=2
ceci affichera 1 et donnera l'erreur "MY_VAR: readonly variable" pour la seconde tâche.
Puisque c'est marqué shell
, il est important de noter que declare
est un mot-clé valide seulement dans un ensemble limité de shells, donc si elle supporte -g est discutable. Pour faire ce genre de chose dans un shell Bourne Générique, vous pouvez simplement utiliser eval:
eval ${arg}=5
je pense que vous avez besoin de l' printf
construire avec son -v
switch:
func() {
printf -v "$var" '5'
}
var=var_name
func
echo "$var_name"
sortie 5
.
utiliser "eval" (ou n'importe quelle assignation directe) peut vous donner des maux de tête avec des caractères spéciaux (ou des problèmes avec l'injection de valeur etc).
j'ai eu beaucoup de succès en utilisant simplement sur "lire"
$ function assign_global() {
> local arg=""
> IFS="" read -d "" $arg <<<""
>}
$ 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 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 tableaux à l'intérieur d'une définition de fonction, vous pouvez utiliser le local
commande en combinaison avec l' eval
commande comme dans l'exemple suivant:
#!/bin/bash
function test
{
local -g
local array=( AA BB 'C C' DD)
eval ='("${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 des variables de tableau...J'ai juste dû citer la variable Local Array à l'intérieur de la déclaration eval.
ce qui suit lit dans un fichier (1ère arg) une ligne à la fois et le copie ensuite au nom de la variable passé au 2ème arg du get_file.
get_file () {
declare -a Array=();
while read line; do
Array=("${Array[@]}" "($line)")
done <
eval ='("${Array[@]}")'
unset Array
}
declare -a my_array=();
get_file /etc/myfile.conf my_array
echo ${#my_array[@]}
peut-être que vous pourriez utiliser les fonctions suivantes pour assigner dynamiquement votre variable globale dans bash(< 4.2). Si > 2 args passés, alors la valeur sera de type array. E. G
_set2globals variable_name arg1 [arg2] [arg3] [...]
Source:
# dynamically set $variable_name()=$values(...) 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 [[ ! =~ $___pattern_ ]]; then
printf "$FUNCNAME: invalid variable name: %s.\n" "" >&2
exit 1
fi
local __variable__name__=
shift
local ___v_
local ___values_=()
while (($# > 0)); do
___v_=\'${1//"'"/"'\''"}\'
___values_=("${___values_[@]}" "$___v_") # push to array
shift
done
eval $__variable__name__=\("${___values_[@]}"\)
}