GNU/Linux >> Tutoriales Linux >  >> Linux

¿Referencias de nombres circulares en la función Bash Shell, pero no en Ksh?

Estoy escribiendo un conjunto de funciones de shell que quiero que funcionen tanto en Bash como en KornShell93, pero con Bash me encuentro con una advertencia de "referencia de nombre circular".

Esta es la esencia del problema:

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"

Ejecutándolo:

$ ksh script.sh
hello:boff

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

KornShell93 hace exactamente lo que quiero, pero Bash falla y también advierte sobre lo mismo en la línea 2 si something variable en el script se llama var en su lugar.

Me gustaría tener la var la variable sea local para cada función, por eso uso typeset , pero a Bash no parece gustarle "desreferenciar" una referencia de nombre a una variable con el mismo nombre que la referencia de nombre. No puedo usar local -n o declare -n ya que se rompería en ksh que carece de estos, e incluso si los tuviera, no resuelve el problema.

La única solución que he encontrado es usar nombres de variables únicos en cada función , lo que parece bastante tonto ya que son locales.

El manual de Bash dice lo siguiente sobre typeset :

typeset […]

-n Asigne a cada nombre el nameref atributo, convirtiéndolo en una referencia de nombre
a otra variable. Esa otra variable está
definida por el valor de name . Todas las referencias y
asignaciones a name , excepto por cambiar el -n
atributo en sí mismo, se realizan en la variable a la que hace referencia el valor del nombre.

[…]

Cuando se usa en una función, declare y typeset hacer que cada nombre
sea local, como con el local comando, a menos que -g la opción es
suministrada. Si el nombre de una variable va seguido de =value , el valor
de la variable se establece en value .

Es obvio que hay algo que no entiendo sobre las referencias de nombres de Bash y las variables locales de funciones.

Entonces, la pregunta es:en este caso, ¿me estoy perdiendo algo sobre el manejo de Bash de las variables de referencia de nombre, o se trata de un error/función incorrecta en Bash?

Actualizar :actualmente estoy trabajando con GNU bash, version 4.3.39(1)-release (x86_64-apple-darwin15) así como con GNU bash, version 4.3.46(1)-release (x86_64-unknown-openbsd6.0) . El Bash enviado con macOS es demasiado antiguo para conocer las referencias de nombres.

Actualizar :Aún más corto:

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

var="hello"
bug var

Resultados en bash: warning: var: circular name reference . El var en la función debería tener un alcance diferente de la var en el ámbito mundial. Esto impone una restricción innecesaria a la persona que llama. La restricción es "no se le permite nombrar sus variables como quiera, porque puede haber un conflicto de nombres con una referencia de nombre (local) en esta función".

Relacionado:¿Cómo cambiar de usuario root a otro usuario que tiene un shell de nologin?

Respuesta aceptada:

Chet Ramey (mantenedor de Bash) dice

Hubo una extensa discusión sobre las referencias de nombre en bug-bash a principios de este
año. Tengo una sugerencia razonable sobre cómo cambiar este comportamiento,
y la revisaré después de que se publique bash-4.4.

Mientras tanto, estoy recurriendo a ofuscar un poco los nombres de mis variables nameref locales, para que no entren en conflicto dentro de la biblioteca ni (con suerte) con los nombres de variables de shell global.

En bash 5.0, esto se remedió ligeramente (pero no se solucionó realmente). El siguiente es el comportamiento observado:

$ 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

Esto muestra que funciona, pero que también hay algunas advertencias.

La entrada de NOTICIAS relevante dice

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

Linux
  1. ¿Diferencia entre las variables de Shell que se exportan y las que no están en Bash?

  2. ¿Por qué el documento principal Shell Here no funciona para el subcomando en Dash pero Bash funciona?

  3. Cualquier forma de salir del script bash, pero sin salir de la terminal

  4. El comando Conda funciona en el símbolo del sistema pero no en el script bash

  5. ¿Por qué Bash está en todas partes (en la mayoría, si no en todas, las distribuciones de Linux)?

Funciones bash

.bashrc frente a .bash_profile

Shell Scripting Parte V:Funciones en Bash

¿Funciones en variables de Shell?

Comandos útiles de Bash que quizás no conozcas

Tutorial de funciones de Bash Shell con 6 ejemplos prácticos