GNU/Linux >> Tutoriels Linux >  >> Linux

Références de noms circulaires dans la fonction Bash Shell, mais pas dans Ksh ?

J'écris un ensemble de fonctions shell que je souhaite faire fonctionner à la fois dans Bash et KornShell93, mais avec Bash, je rencontre un avertissement "référence de nom circulaire".

C'est l'essence du problème :

function set_it {
    typeset -n var="$1"

    var="hello:$var"
}

function call_it {
    typeset -n var="$1"

    set_it var
}

something="boff"
call_it something
echo "$something"

Exécution :

$ ksh script.sh
hello:boff

$ bash script.sh
script.sh: line 4: warning: var: circular name reference
hello:

KornShell93 fait exactement ce que je veux, mais Bash échoue et avertit également de la même chose à la ligne 2 si le something la variable dans le script est nommée var à la place.

J'aimerais avoir la var la variable soit locale à chaque fonction, c'est pourquoi j'utilise typeset , mais Bash ne semble pas aimer "déréférencer" un nameref à une variable portant le même nom que le nameref lui-même. Je ne peux pas utiliser local -n ou declare -n car il briserait ksh qui en manque, et même si c'était le cas, cela ne résout pas le problème.

La seule solution que j'ai trouvée est d'utiliser des noms de variables uniques dans chaque fonction , ce qui semble plutôt idiot puisqu'ils sont locaux.

Le manuel Bash dit ce qui suit à propos de typeset :

typeset […]

-n Donnez à chaque nom le nameref attribut, ce qui en fait une référence de nom
à une autre variable. Cette autre variable est
définie par la valeur de name . Toutes les références et
affectations à name , sauf pour changer le -n
attribut lui-même, sont effectuées sur la variable référencée par la valeur du nom.

[…]

Lorsqu'il est utilisé dans une fonction, declare et typeset rendre chaque nom
local, comme avec le local commande, sauf si la commande -g option est
fournie. Si un nom de variable est suivi de =value , la
valeur de la variable est définie sur value .

Il est évident qu'il y a quelque chose que je ne comprends pas à propos des références de nom et des variables locales de fonction de Bash.

Donc, la question est :dans ce cas, ai-je raté quelque chose concernant la gestion par Bash des variables de référence de nom, ou s'agit-il d'un bogue/d'une mauvaise fonctionnalité dans Bash ?

Mettre à jour :Je travaille actuellement avec GNU bash, version 4.3.39(1)-release (x86_64-apple-darwin15) ainsi qu'avec GNU bash, version 4.3.46(1)-release (x86_64-unknown-openbsd6.0) . Le Bash fourni avec macOS est trop ancien pour connaître les références de noms.

Mettre à jour :Encore plus court :

function bug {
    typeset -n var="$1"
    printf "%sn" "$var"
}

var="hello"
bug var

Résultats dans bash: warning: var: circular name reference . La var dans la fonction devrait avoir une portée différente de la var dans le périmètre global. Cela impose une restriction inutile à l'appelant. La restriction étant "vous n'êtes pas autorisé à nommer vos variables comme vous le souhaitez, car il peut y avoir un conflit de nom avec un nameref (local) dans cette fonction".

En relation :Comment passer d'un utilisateur root à un autre utilisateur disposant d'un shell nologin ?

Réponse acceptée :

Chet Ramey (responsable de Bash) dit

Il y a eu une discussion approfondie sur les namerefs sur bug-bash plus tôt cette
année. J'ai une suggestion raisonnable sur la façon de modifier ce comportement,
et je l'examinerai après la sortie de bash-4.4.

En attendant, j'ai recours à un peu d'obscurcissement des noms de mes variables nameref locales, afin qu'elles n'entrent pas en conflit dans la bibliothèque ni (espérons-le) avec les noms de variables shell globales.

Dans bash 5.0, cela est légèrement corrigé (mais pas vraiment corrigé). Voici le comportement observé :

$ foo () { typeset -n var="$1"; echo "$var"; }
$ var=hello
$ foo var
bash: typeset: warning: var: circular name reference
bash: warning: var: circular name reference
bash: warning: var: circular name reference
hello

Cela montre que cela fonctionne, mais qu'il y a aussi quelques avertissements.

L'entrée NEWS correspondante indique

i. A nameref name resolution loop in a function now resolves to a variable by
that name in the global scope.

Linux
  1. Différence entre les variables Shell qui sont exportées et celles qui ne sont pas dans Bash ?

  2. Commande introuvable dans Zsh, mais trouvée dans Bash ?

  3. Modules Python introuvables sur le terminal mais sur le shell Python, Linux

  4. Comment désactiver ou supprimer une fonction bash ?

  5. bash - supprime tous les répertoires (et contenus) mais pas les fichiers dans pwd

Fonctions bash

.bashrc contre .bash_profile

Shell Scripting Partie V :Fonctions dans Bash

Commandes Bash utiles que vous ne connaissez peut-être pas

Tutoriel sur les fonctions Bash Shell avec 6 exemples pratiques

Autoriser SCP mais pas la connexion réelle à l'aide de SSH