Exportar una variable con un punto (.)

Exportar una variable con un punto (.)

Cómo exportar una variable que tiene un punto. Recibo un 'nombre de variable no válido' cuando intenté:

 export my.home=/tmp/someDir
-ksh: my.home=/tmp/someDir: invalid variable name

Incluso escapar del punto de metacarácter (.) tampoco ayudó

$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier

Respuesta1

Al menos para bashla página de manual define la sintaxis de exportación como:

export [-fn] [name[=word]] ...

También define un "nombre" como:

   name   A  word  consisting  only  of alphanumeric characters and under‐
          scores, and beginning with an alphabetic character or an  under‐
          score.  Also referred to as an identifier.

Por lo tanto, realmente no se puede definir una variable como my.homeya que no es un identificador válido.

Estoy muy seguro de que su ksh tiene una definición muy similar de identificador y, por lo tanto, tampoco permite este tipo de variables. (Eche un vistazo a su página de manual).

También estoy muy seguro de que existe algún tipo de estándar general (¿POSIX?) que especifica qué está permitido como identificador (y, por lo tanto, como nombre de variable).


Si realmente necesitas este tipo de variable por algún motivo, puedes usar algo como

env "my.home=/tmp/someDir" bash

definirlo de todos modos. Pero, de nuevo, no podrá acceder a él utilizando la sintaxis normal del shell. En este caso probablemente necesites otro lenguaje como perl:

perl -e 'print $ENV{"my.home"}'

Por ejemplo

env "my.home=/tmp/someDir" perl -le 'print $ENV{"my.home"}'

debería imprimir su ruta.

Respuesta2

Si bien las variables de entorno pueden tener cualquier nombre (incluida la cadena vacía) que no contenga un signo igual o un byte nulo, los shells asignan variables de entorno a variables de shell y, en la mayoría de los shells, los nombres de las variables se limitan a caracteres alfanuméricos ASCII y _el primer carácter puede Será un dígito (excepto los parámetros posicionales y otros especiales como $*,,, …, ( $-que $@no están asignados a las variables de entorno correspondientes)). También tenga en cuenta que algunas variables sonreservado/especialpor/al caparazón.

Excepciones a eso:

  • Al rcshell y sus derivados les gusta esy admiten cualquier nombre excepto la cadena vacía, y aquellos que akangason completamente numéricos o contienen =caracteres (y siempre exportan todas sus variables al entorno, y tengan cuidado con las variables especiales como *,, ...):statuspid

    ; '%$£"' = test
    ; echo $'%$£"'
    test
    ; '' = x
    zero-length variable name
    ;
    

    Sin embargo, utiliza su propia codificación para variables cuyo nombre no contiene alnums o para matrices cuando se pasa en el entorno de los comandos que se ejecutan:

    $ rc -c '+ = zzz; __ = zzz; a = (zzz xxx); env' | sed -n /zzz/l
    __2b=zzz$
    __5f_=zzz$
    a=zzz\001xxx$
    $ env +=x rc -c "echo $'+'"
    x
    $ env __2b=x rc -c "echo $'+'"
    x
    
  • AT&T kshy yash( zshtambién, bashpero solo para caracteres de un solo byte) admiten números en la configuración regional actual, no solo en ASCII.

    $ Stéphane=1
    $ echo "$Stéphane"
    1
    

    En esos shells, podrías cambiar la configuración regional para considerar a la mayoría de los caracteres como alfa, pero aun así eso no funcionaría para caracteres ASCII como .. Puedes engañarte zsho kshpensar £que es una letra, pero no esa .ni ningún otro carácter ASCII (en lo que respecta a permitir caracteres en nombres de variables, no para el [[:alpha:]]globo, por ejemplo).

  • ksh93tiene variables especiales cuyo nombre contiene un punto como ${.sh.version}, pero no están asignadas a variables de entorno y son especiales. El .objetivo es asegurarse de que no entre en conflicto con otras variables. Si hubiera elegido llamarlo $sh_version, entonces podría tener scripts potencialmente rotos que ya usaban esa variable (vea, por ejemplo, cómo zshtiene problemas con sus $pathvariables $commandsde matriz/hash especiales (a la csh) que rompen algunos scripts).

Tenga en cuenta que, además de los shells que no admiten esas variables, algunos shells como pdksh/mksh sí lo hacen.eliminardel entorno que reciben ( bashelimina el que tiene un nombre vacío ashy elimina aquellas cadenas kshde bashentorno que no contienen un =carácter):

$ env %%%=test 1=%%% a.b=%%% mksh -c env | grep %%%
$ env %%%=test 1=%%% a.b=%%% bash -c env | grep %%%
%%%=test
a.b=%%%
1=%%%

$ perl -le '$ENV{""}="%%%"; exec "bash", "-c", "env"' | grep %%%
$ perl -le '$ENV{""}="%%%"; exec "zsh", "-c", "env"' | grep %%%
=%%%

$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
    execve("/bin/ash",a,e);}'|tcc -run - | grep %%%
$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
    execve("/bin/zsh",a,e);}'|tcc -run - | grep %%%
%%%

En resumen, lo mejor es seguir con los nombres de variables admitidos por la mayoría de los shells e incluso intentar usar mayúsculas para las variables de entorno (y minúsculas o mixtas para las variables de shell no exportadas) evitando aquellos que son especiales en los shells (como IFS, PS1, BASH_VERSION...).

Si necesita establecer dicha variable en un shell que no las admite, pero que no las descarta, puede volver a ejecutarlas usted mismo con algo como:

#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"

(Obviamente, si necesitas hacerlo en medio del guión, eso no ayudará, pero luego puedes echar un vistazo aese enfoquepara guardar y restaurar el entorno de ejecución del shell mediante una nueva ejecución). O pruebe el enfoque del depurador:

gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"

(ese parece funcionar con zsh, y en Linux amd64, pero no con ninguno de los otros shells yashque probé ( ,,,, ) ).cshtcshmkshksh93bashdash

Respuesta3

Como señalan las otras publicaciones, los shells más comunes no permiten configurar variables de entorno con puntos en el nombre. Sin embargo, he encontrado situaciones, particularmente relacionadas con Docker y programas invocados, donde el software requería valores clave con puntos.

Sin embargo, en cada una de estas situaciones, esos pares clave-valor podrían pasarse al programa por otros medios además de las variables de entorno. Por ejemplo, en Ant, puede utilizar "-propertyfile (nombre de archivo)" para pasar una colección de valores-clave formateada en un archivo de propiedades. Confd permite "-archivo backend -file (archivo yaml)".

Pasé las variables de entorno en el formato "C__any_value='my.property.key=the value'". Luego cambié la invocación del programa para generar primero el archivo:

set | awk -- 'BEGIN { FS="'\''" } /^C__/ {print $2}' > my-key-values.txt

El setcomando, en Borne Shell, generará cada propiedad en una línea separada en el formulario

C__any_value='my.property.key=the value'

El awkcomando procesará solo las variables de entorno que comienzan con C__y luego extraerá los valores contenidos entre comillas simples.

Este método requiere que el valor de la variable de entorno se establezca en la forma precisa que requiere el programa de procesamiento. Además, si el valor o la clave de su propiedad contendrá comillas simples, deberá cambiar el carácter separador del campo awk por algo que sepa que no aparecerá y rodear el valor con ese carácter. Por ejemplo, para usar %como separador:

$ C__1="%my.key=the'value%"
$ set | awk -- 'BEGIN { FS="%" } /^C__/ {print $2}'
my.key=the'"'"'value

(La salida precisa dependerá de su shell). Deberá realizar pasos adicionales para decodificar la cita que se escapa.

Respuesta4

La respuesta de @michas es bastante correcta, pero es posible ampliarla para simular exportfunciones con nombres de entorno de puntos.

Para "exportar" dicha variable, puede execactualizar el shell con envel comando. Por ejemplo, para exportar test.env=foovariables, utilice:

exec env "test.env=foo" $SHELL

Exec reemplazará el shell actual con un nuevo proceso, donde el nuevo proceso será una nueva instancia del shell actual ( $SHELL) con una variable de entorno adicional test.env(agregada por env "test.env=foo"). Entonces, después de este comando puedes acceder a él desde tu proceso, por ejemplo:

perl -e 'print $ENV{"test.env"}'

información relacionada