116 votes

Désactiver une variable en lecture seule en bash

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 ?

2voto

jaypal Points 34440

Non, pas dans la coquille actuelle. Si vous souhaitez lui attribuer une nouvelle valeur, vous devrez forker un nouveau shell où elle aura une nouvelle signification et ne sera pas considérée comme read only .

$ { ( readonly pi=3.14; echo $pi ); pi=400; echo $pi; unset pi; echo [$pi]; }
3.14
400
[]

2voto

bufh Points 350

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

2voto

Robin A. Meade Points 340
$ 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 :

  1. Testé avec bash 5.0.17 y gdb 10.1 .
  2. Le site -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
  3. Notez la distribution à 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 .
  4. Cette réponse est essentiellement la même que une réponse sur le site superuser.com . J'ai ajouté le casting à int pour passer le unknown return type erreur.

1voto

Yu Hao Points 40603

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.

1voto

Wil Points 51

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.com

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.

Powered by:

X