Comment annuler la définition d'une variable en lecture seule dans Bash ?
$ readonly PI=3.14
$ unset PI
bash: PI: readonly variable
ou ce n'est pas possible ?
Comment annuler la définition d'une variable en lecture seule dans Bash ?
$ readonly PI=3.14
$ unset PI
bash: PI: readonly variable
ou ce n'est pas possible ?
Une autre solution sans GDB ou un binaire externe (en fait, l'accent est mis sur Graham Nicholls ) serait l'utilisation de exec
.
Dans mon cas, il y avait une variable ennuyeuse en lecture seule dans le fichier /etc/profile.d/xxx
.
Je cite le manuel de bash :
"Lorsque bash est invoqué comme un shell de connexion interactif [...], il lit et exécute d'abord les commandes du fichier /etc/profile" [...]
Lorsqu'un shell interactif qui n'est pas un shell de connexion est lancé, bash lit et exécute les commandes de /etc/bash.bashrc [...]
L'essentiel de ma solution de contournement était de mettre dans ma ~/.bash_profile
:
if [ -n "$annoying_variable" ]
then exec env annoying_variable='' /bin/bash
# or: then exec env -i /bin/bash
fi
Attention : pour éviter une récursion (qui vous bloquerait si vous ne pouvez accéder à votre compte que par SSH), il faut s'assurer que la "variable gênante" ne sera pas automatiquement définie par le bashrc ou définir une autre variable sur la vérification, par exemple :
if [ -n "$annoying_variable" ] && [ "${SHLVL:-1}" = 1 ]
then exec env annoying_variable='' SHLVL=$((SHLVL+1)) ${SHELL:-/bin/bash}
fi
$ readonly PI=3.14
$ unset PI
bash: PI: readonly variable
$ gdb --batch-silent --pid=$$ --eval-command='call (int) unbind_variable("PI")'
$ [[ ! -v PI ]] && echo "PI is unset "
PI is unset
Notes :
bash 5.0.17
y gdb 10.1
.-v varname
a été ajouté dans bash 4.2
. C'est " True
si la variable shell varname
est fixé (on lui a attribué une valeur)". - manuel de référence bash
int
. Sans cela, l'erreur suivante se produira : 'unbind_variable' has unknown return type; cast the call to its declared return type
. Le site code source bash montre que le type de retour de la méthode unbind_variable
La fonction est int
.int
pour passer le unknown return type
erreur.Vous ne pouvez pas, de la page de manuel de unset
:
Pour chaque nom, supprimez la variable ou la fonction correspondante. Si aucune option n'est fournie, ou si l'option -v est donnée, chaque nom fait référence à une variable shell. Les variables en lecture seule ne peuvent pas être désactivées. Si l'option -f est spécifiée, chaque nom fait référence à une fonction de l'interpréteur de commandes, et l'option définition de la fonction est supprimée. Chaque variable ou fonction non définie est supprimée de l'environnement transmis aux commandes suivantes. Si l'une des variables RANDOM, SECONDS, LINENO, HISTCMD, FUNCNAME, GROUPS ou DIRSTACK est désactivée, elle perd ses propriétés particulières, même si elle est même si elles sont réinitialisées par la suite. L'état de sortie est vrai, sauf si un nom est en lecture seule.
Une autre façon de "désélectionner" une variable en lecture seule dans Bash est de déclarer cette variable en lecture seule dans un contexte jetable :
foo(){ declare -r PI=3.14; baz; }
bar(){ local PI=3.14; baz; }
baz(){ PI=3.1415927; echo PI=$PI; }
foo;
bash : PI : variable en lecture seule
bar;
PI=3.1415927
Bien qu'il ne s'agisse pas d'un "unsetting" à l'intérieur de la portée, ce qui est probablement l'intention de l'auteur original, il s'agit certainement de définir une variable en lecture seule du point de vue de baz() et de la rendre plus tard en lecture-écriture du point de vue de baz(), vous devez juste écrire votre script avec un peu de prévoyance.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.