Espacios de nombres separados para funciones y variables en shells POSIX

13

En el guión, las funciones y variables parecen vivir en espacios de nombres separados:

fn(){
    fn="hello world"
}
fn; echo "The value is $fn!" #prints: The value is hello world!
fn; echo "The value is $fn!" #prints: The value is hello world!
#the fn variable doesn't conflict with the fn function

¿Es esta una característica específica del guión o una garantía POSIX?

PSkocik
fuente
2
Su código en realidad no prueba que la fnfunción esté en un espacio de nombres separado; si ejecutarlo una vez hubiera borrado su definición, veríamos exactamente el mismo comportamiento. Debe mostrar que la función aún está definida, por ejemplo, con type fndespués.
alexis

Respuestas:

13

Una garantía :

2.9.5 Comando de definición de funciones

Una función es un nombre definido por el usuario que se usa como un comando simple para llamar a un comando compuesto con nuevos parámetros posicionales. Una función se define con un "comando de definición de función". [...]

La función se llama fname; la aplicación se asegurará de que sea un nombre (ver Nombre XBD) y que no sea el nombre de una utilidad incorporada especial. Una implementación puede permitir otros caracteres en el nombre de una función como una extensión. La implementación mantendrá espacios de nombres separados para funciones y variables.

ilkkachu
fuente
También tenga en cuenta que unsettiene -vy -fpara elegir entre desarmar la variable o función por el nombre dado. bash(a diferencia de la mayoría de las otras conchas) se desarmará la foo función de unset foosi no hay foovariable (!), un comportamiento permitido por POSIX. Es por eso que en los scripts POSIX es una buena práctica usar siempre uno -vo -f(y, por supuesto, también en los bashscripts, pero tenga en cuenta que unsetno siempre puede desarmar una variable bash, el bashalcance de la variable tiene bastantes problemas).
Stéphane Chazelas
Tenga en cuenta que en pre-shellshock bash, tendría problemas al exportar la variable y la función por un nombre dado, ya que bash terminaría usando el mismo nombre de variable de entorno para ambos (poniéndolo dos veces en el entorno, algunos comandos podrían eliminar uno de ellos)
Stéphane Chazelas
8

Las variables y funciones residen en diferentes espacios de nombres en el guión y esto también lo especifica POSIX :

La implementación mantendrá espacios de nombres separados para funciones y variables.

Además de eso, las variables tienen alcance global, por defecto. Algunos shells (por ejemplo, bash, ksh y zsh) proporcionan la localpalabra clave para declarar variables en una función solo con alcance local.

Entonces, sí, el comportamiento que está viendo está garantizado por POSIX.

POSIX no ha estandarizado local , sin embargo :

La descripción de las funciones en una propuesta inicial se basaba en la noción de que las funciones deberían comportarse como scripts de shell en miniatura; es decir, excepto para compartir variables , la mayoría de los elementos de un entorno de ejecución deberían comportarse como si fueran un nuevo entorno de ejecución, [..]

[..] Las variables locales dentro de una función se consideraron e incluyeron en otra propuesta inicial (controlada por el incorporado especial local), pero se eliminaron porque no se ajustan al modelo simple desarrollado para las funciones y porque había cierta oposición a agregar aún Otro nuevo especial incorporado que no era parte de la práctica histórica. Las implementaciones deben reservar el identificador local(así como typeset, como se usa en KornShell) en caso de que este mecanismo de variable local se adopte en una versión futura de este estándar.

(énfasis mío)

maxschlepzig
fuente
Ash (de finales de los 80) en el que se basa el guión también tiene local, una de las interfaces más consistentes que existen (en comparación con la severamente rota en bash, por ejemplo), bash solo recientemente (4.4) tomó prestado el local -(para el alcance local para opciones) de ash (implementando un alcance de estilo ash solo para esa $-variable). ksh y yash no tienen local(solo las variantes pdksh tienen local), sino que tienen typeset(en ksh93 typesetproporciona un alcance local (estático) solo en funciones declaradas usando la sintaxis ksh).
Stéphane Chazelas